/** * This creates a dropdown menu that's populated with possible field key names (e.g., author, tags) * * The set of field names actually displayed is based on searching the prop 'Document' and its descendants : * The field list will contain all of the fields within the prop Document and all of its children; * this list is then pruned down to only include fields that are not marked in Documents.ts to be non-filterable */ import { computed, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import Select from 'react-select'; import { Doc } from '../../fields/Doc'; import { DocOptions, FInfo } from '../documents/Documents'; import { SearchUtil } from '../util/SearchUtil'; import { SnappingManager } from '../util/SnappingManager'; import './FilterPanel.scss'; import { ObservableReactComponent } from './ObservableReactComponent'; interface fieldsDropdownProps { Document: Doc; // show fields for this Doc if set, otherwise for all docs in dashboard selectFunc: (value: string) => void; menuClose?: () => void; placeholder?: string | (() => string); showPlaceholder?: true; // if true, then input field always shows the placeholder value; otherwise, it shows the current selection addedFields?: string[]; } @observer export class FieldsDropdown extends ObservableReactComponent { @observable _newField = ''; constructor(props: any) { super(props); makeObservable(this); } @computed get allDescendantDocs() { //!!! const allDocs = new Set(); SearchUtil.foreachRecursiveDoc([this._props.Document], (depth, doc) => allDocs.add(doc)); return Array.from(allDocs); } @computed get fieldsOfDocuments() { const keys = new Set(); this.allDescendantDocs.forEach(doc => SearchUtil.documentKeys(doc).filter(key => keys.add(key))); const sortedKeys = Array.from(keys.keys()) .filter(key => key[0]) .filter(key => key.indexOf('modificationDate') !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith('_')) || !Doc.noviceMode) .sort(); Array.from(keys).forEach(key => sortedKeys.splice(sortedKeys.indexOf(key), 1)); return [...Array.from(keys), ...sortedKeys]; } render() { const filteredOptions = ['author', ...(this._newField ? [this._newField] : []), ...(this._props.addedFields ?? []), ...this.fieldsOfDocuments.filter(facet => facet[0] === facet.charAt(0).toUpperCase())]; Object.entries(DocOptions) .filter(opts => opts[1].filterable) //!!! .forEach((pair: [string, FInfo]) => filteredOptions.push(pair[0])); const options = filteredOptions.sort().map(facet => ({ value: facet, label: facet })); return (