From 4548ec81efc434c8ee5d89b896b2088e4e61d7a0 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 28 Feb 2024 22:22:20 -0500 Subject: extracted field dropdown menu to a components and then cleaned up collectionTimeView, Documentview titles, and FilterPanel to share it --- src/client/views/FieldsDropdown.tsx | 120 ++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 src/client/views/FieldsDropdown.tsx (limited to 'src/client/views/FieldsDropdown.tsx') diff --git a/src/client/views/FieldsDropdown.tsx b/src/client/views/FieldsDropdown.tsx new file mode 100644 index 000000000..5638d34c6 --- /dev/null +++ b/src/client/views/FieldsDropdown.tsx @@ -0,0 +1,120 @@ +/** + * 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 { SettingsManager } from '../util/SettingsManager'; +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 })); + + console.log(options); + return ( +