diff options
Diffstat (limited to 'src/client/views/nodes')
| -rw-r--r-- | src/client/views/nodes/DocumentView.scss | 57 | ||||
| -rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 12 | ||||
| -rw-r--r-- | src/client/views/nodes/FilterBox.scss | 168 | ||||
| -rw-r--r-- | src/client/views/nodes/FilterBox.tsx | 309 |
4 files changed, 487 insertions, 59 deletions
diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss index 749ffa7fd..36572b861 100644 --- a/src/client/views/nodes/DocumentView.scss +++ b/src/client/views/nodes/DocumentView.scss @@ -3,6 +3,7 @@ .documentView-effectsWrapper { border-radius: inherit; } + .documentView-node, .documentView-node-topmost { position: inherit; @@ -37,12 +38,13 @@ overflow-y: scroll; height: calc(100% - 20px); } + .documentView-linkAnchorBoxAnchor { - display:flex; + display: flex; overflow: hidden; .documentView-node { - width:10px !important; + width: 10px !important; } } @@ -64,6 +66,7 @@ top: 15%; } } + .documentView-treeView { max-height: 1.5em; text-overflow: ellipsis; @@ -71,7 +74,8 @@ white-space: pre; width: 100%; overflow: hidden; - > .documentView-node { + + >.documentView-node { position: absolute; } } @@ -80,14 +84,33 @@ border-radius: inherit; width: 100%; height: 100%; + + .sharingIndicator { + height: 30px; + width: 30px; + border-radius: 50%; + position: absolute; + right: -15; + opacity: 0.9; + pointer-events: auto; + background-color: #9dca96; + letter-spacing: 2px; + font-size: 10px; + transition: transform 0.2s; + text-align: center; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; + } } .documentView-anchorCont { position: absolute; - top: 0; - left: 0; + top: 0; + left: 0; width: 100%; - height: 100%; + height: 100%; display: inline-block; pointer-events: none; } @@ -100,6 +123,7 @@ top: 0; left: 0; } + .documentView-styleWrapper { position: absolute; display: inline-block; @@ -113,7 +137,8 @@ position: absolute; } - .documentView-titleWrapper, .documentView-titleWrapper-hover { + .documentView-titleWrapper, + .documentView-titleWrapper-hover { overflow: hidden; color: white; transform-origin: top left; @@ -126,8 +151,9 @@ white-space: pre; position: absolute; } + .documentView-titleWrapper-hover { - display:none; + display: none; } .documentView-searchHighlight { @@ -150,18 +176,21 @@ } -.documentView-node:hover, .documentView-node-topmost:hover { - > .documentView-styleWrapper { - > .documentView-titleWrapper-hover { - display:inline-block; +.documentView-node:hover, +.documentView-node-topmost:hover { + >.documentView-styleWrapper { + >.documentView-titleWrapper-hover { + display: inline-block; } } - > .documentView-styleWrapper { - > .documentView-captionWrapper { + + >.documentView-styleWrapper { + >.documentView-captionWrapper { opacity: 1; } } } + .contentFittingDocumentView { position: relative; display: flex; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 26cf52f17..1c4008a55 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -11,7 +11,7 @@ import { listSpec } from "../../../fields/Schema"; import { ScriptField } from '../../../fields/ScriptField'; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Types"; import { AudioField } from "../../../fields/URLField"; -import { GetEffectiveAcl, TraceMobx } from '../../../fields/util'; +import { GetEffectiveAcl, SharingPermissions, TraceMobx } from '../../../fields/util'; import { MobileInterface } from '../../../mobile/MobileInterface'; import { emptyFunction, hasDescendantTarget, OmitKeys, returnVal, Utils } from "../../../Utils"; import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils'; @@ -124,6 +124,8 @@ export interface DocumentViewSharedProps { disableDocBrushing?: boolean; // should highlighting for this view be disabled when same document in another view is hovered over. pointerEvents?: string; scriptContext?: any; // can be assigned anything and will be passed as 'scriptContext' to any OnClick script that executes on this document + createNewFilterDoc?: () => void; + updateFilterDoc?: (doc: Doc) => void; } export interface DocumentViewProps extends DocumentViewSharedProps { // properties specific to DocumentViews but not to FieldView @@ -599,7 +601,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps if (this.props.Document === CurrentUserUtils.ActiveDashboard) { alert((e.target as any)?.closest?.("*.lm_content") ? "You can't perform this move most likely because you don't have permission to modify the destination." : - "linking to document tabs not yet supported. Drop link on document content."); + "Linking to document tabs not yet supported. Drop link on document content."); return; } const linkdrag = de.complete.annoDragData ?? de.complete.linkDragData; @@ -792,6 +794,12 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps </div>; } + get indicatorIcon() { + if (this.props.Document["acl-Public"] !== SharingPermissions.None) return "globe-americas"; + else if (this.props.Document.numGroupsShared || NumCast(this.props.Document.numUsersShared, 0) > 1) return "users"; + else return "user"; + } + @undoBatch hideLinkAnchor = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && (doc.hidden = true), true) anchorPanelWidth = () => this.props.PanelWidth() || 1; diff --git a/src/client/views/nodes/FilterBox.scss b/src/client/views/nodes/FilterBox.scss index d32cc0d2b..107ad2e36 100644 --- a/src/client/views/nodes/FilterBox.scss +++ b/src/client/views/nodes/FilterBox.scss @@ -1,17 +1,155 @@ - - .filterBox-flyout { - width: 400px; display: block; text-align: left; + font-weight: 100; + .filterBox-flyout-facet { - background-color: lightgray; - text-align: left; - display: inline-block; - position: relative; - width: 100%; + background-color: white; + text-align: left; + display: inline-block; + position: relative; + width: 100%; + + .filterBox-flyout-facet-check { + margin-right: 6px; + } + } +} + + +.filter-bookmark { + //display: flex; + + .filter-bookmark-icon { + float: right; + margin-right: 10px; + margin-top: 7px; + } +} + +// .filterBox-bottom { +// // position: fixed; +// // bottom: 0; +// // width: 100%; +// } + +.filterBox-select { + // width: 90%; + margin-top: 5px; + // margin-bottom: 15px; +} + + +.filterBox-saveBookmark { + background-color: #e9e9e9; + border-radius: 11px; + padding-left: 8px; + padding-right: 8px; + padding-top: 5px; + padding-bottom: 5px; + margin: 8px; + display: flex; + font-size: 11px; + cursor: pointer; + + &:hover { + background-color: white; + } + + .filterBox-saveBookmark-icon { + margin-right: 6px; + margin-top: 4px; + margin-left: 2px; + } + +} + +.filterBox-select-scope, +.filterBox-select-bool, +.filterBox-addWrapper, +.filterBox-select-matched, +.filterBox-saveWrapper { + font-size: 10px; + justify-content: center; + justify-items: center; + padding-bottom: 10px; + display: flex; +} + +.filterBox-addWrapper { + font-size: 11px; + width: 100%; +} + +.filterBox-saveWrapper { + width: 100%; +} + +// .filterBox-top { +// padding-bottom: 20px; +// border-bottom: 2px solid black; +// position: fixed; +// top: 0; +// width: 100%; +// } + +.filterBox-select-scope { + padding-bottom: 20px; + border-bottom: 2px solid black; +} + +.filterBox-title { + font-size: 15; + // border: 2px solid black; + width: 100%; + align-self: center; + text-align: center; + background-color: #d3d3d3; +} + +.filterBox-select-bool { + margin-top: 6px; +} + +.filterBox-select-text { + margin-right: 8px; + margin-left: 8px; + margin-top: 3px; +} + +.filterBox-select-box { + margin-right: 2px; + font-size: 30px; + border: 0; + background: transparent; +} + +.filterBox-selection { + border-radius: 6px; + border: none; + background-color: #e9e9e9; + padding: 2px; + + &:hover { + background-color: white; + } +} + +.filterBox-addFilter { + width: 120px; + background-color: #e9e9e9; + border-radius: 12px; + padding: 5px; + margin: 5px; + display: flex; + text-align: center; + justify-content: center; + + &:hover { + background-color: white; } } + .filterBox-treeView { display: flex; flex-direction: column; @@ -20,24 +158,23 @@ position: absolute; right: 0; top: 0; - border-left: solid 1px; z-index: 1; + background-color: #9F9F9F; + + .filterBox-tree { + z-index: 0; + } .filterBox-addfacet { display: inline-block; width: 200px; height: 30px; - background: darkGray; text-align: left; .filterBox-addFacetButton { display: flex; margin: auto; cursor: pointer; - - .filterBox-span { - margin-right: 15px; - } } >div, @@ -50,6 +187,7 @@ .filterBox-tree { display: inline-block; width: 100%; - height: calc(100% - 30px); + margin-bottom: 10px; + //height: calc(100% - 30px); } }
\ No newline at end of file diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx index bf8d2b99e..501d02dc4 100644 --- a/src/client/views/nodes/FilterBox.tsx +++ b/src/client/views/nodes/FilterBox.tsx @@ -2,14 +2,14 @@ import React = require("react"); import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { computed, observable, action, trace, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { DataSym, Doc, DocListCast, Field, Opt, DocListCastAsync } from "../../../fields/Doc"; +import { Doc, DocListCast, Field, Opt, DocListCastAsync, HeightSym } from "../../../fields/Doc"; import { documentSchema } from "../../../fields/documentSchemas"; import { List } from "../../../fields/List"; import { RichTextField } from "../../../fields/RichTextField"; import { listSpec, makeInterface } from "../../../fields/Schema"; import { ComputedField, ScriptField } from "../../../fields/ScriptField"; -import { Cast } from "../../../fields/Types"; -import { emptyFunction, emptyPath, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnOne, returnZero, returnTrue } from "../../../Utils"; +import { Cast, StrCast } from "../../../fields/Types"; +import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from "../../../Utils"; import { Docs } from "../../documents/Documents"; import { DocumentType } from "../../documents/DocumentTypes"; import { CollectionDockingView } from "../collections/CollectionDockingView"; @@ -19,18 +19,76 @@ import { SearchBox } from "../search/SearchBox"; import { FieldView, FieldViewProps } from './FieldView'; import './FilterBox.scss'; import { Scripting } from "../../util/Scripting"; +import { SelectionManager } from "../../util/SelectionManager"; import { CollectionView } from "../collections/CollectionView"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; +import Select from "react-select"; +import { UserOptions } from "../../util/GroupManager"; +import { DocumentViewProps } from "./DocumentView"; +import { DefaultStyleProvider, StyleProp } from "../StyleProvider"; +import { CollectionViewType } from "../collections/CollectionView"; +import { CurrentUserUtils } from "../../util/CurrentUserUtils"; +import { EditableView } from "../EditableView"; type FilterBoxDocument = makeInterface<[typeof documentSchema]>; const FilterBoxDocument = makeInterface(documentSchema); @observer export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDocument>(FilterBoxDocument) { + + constructor(props: Readonly<FieldViewProps>) { + super(props); + const targetDoc = FilterBox.targetDoc; + if (targetDoc && !targetDoc.currentFilter) CurrentUserUtils.setupFilterDocs(targetDoc); + } public static LayoutString(fieldKey: string) { return FieldView.LayoutString(FilterBox, fieldKey); } + @observable static _filterScope = "Current Dashboard"; + public _filterSelected = false; + public _filterMatch = "matched"; + + @computed static get currentContainingCollectionDoc() { + let docView: any = SelectionManager.Views()[0]; + let doc = docView.Document; + + while (docView && doc && doc.type !== "collection") { + doc = docView.props.ContainingCollectionDoc; + docView = docView.props.ContainingCollectionView; + } + + return doc; + } + + // /** + // * @returns the relevant doc according to the value of FilterBox._filterScope i.e. either the Current Dashboard or the Current Collection + // */ + + + // trying to get this to work rather than the version below this + + // @computed static get targetDoc() { + // console.log(FilterBox.currentContainingCollectionDoc.type); + // if (FilterBox._filterScope === "Current Collection") { + // return FilterBox.currentContainingCollectionDoc; + // } + // else return CollectionDockingView.Instance.props.Document; + // // return FilterBox._filterScope === "Current Collection" ? SelectionManager.Views()[0].Document || CollectionDockingView.Instance.props.Document : CollectionDockingView.Instance.props.Document; + // } + + + /** + * @returns the relevant doc according to the value of FilterBox._filterScope i.e. either the Current Dashboard or the Current Collection + */ + @computed static get targetDoc() { + console.log("recomputing"); + if (FilterBox._filterScope === "Current Collection") { + return SelectionManager.Views()[0]?.Document.type === "collection" ? SelectionManager.Views()[0].Document : SelectionManager.Views()[0]?.props.ContainingCollectionDoc!; + } + else return CurrentUserUtils.ActiveDashboard; + } + @observable _loaded = false; componentDidMount() { reaction(() => DocListCastAsync(CollectionDockingView.Instance.props.Document.data), @@ -41,16 +99,19 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc }, { fireImmediately: true }); } @computed get allDocs() { + // trace(); const allDocs = new Set<Doc>(); - if (this._loaded && CollectionDockingView.Instance) { - const activeTabs = DocListCast(CollectionDockingView.Instance.props.Document.data); + const targetDoc = FilterBox.targetDoc; + if (this._loaded && targetDoc) { + const activeTabs = DocListCast(targetDoc.data); SearchBox.foreachRecursiveDoc(activeTabs, (doc: Doc) => allDocs.add(doc)); - setTimeout(() => CollectionDockingView.Instance.props.Document.allDocuments = new List<Doc>(Array.from(allDocs))); + setTimeout(() => targetDoc.allDocuments = new List<Doc>(Array.from(allDocs))); } return allDocs; } @computed get _allFacets() { + // trace(); const noviceReqFields = ["author", "tags", "text", "type"]; const noviceLayoutFields: string[] = [];//["_curPage"]; const noviceFields = [...noviceReqFields, ...noviceLayoutFields]; @@ -60,6 +121,21 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc return Array.from(keys.keys()).filter(key => key[0]).filter(key => key[0] === "#" || key.indexOf("lastModified") !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith("_")) || noviceFields.includes(key) || !Doc.UserDoc().noviceMode).sort(); } + + /** + * The current attributes selected to filter based on + */ + @computed get activeAttributes() { + return DocListCast(this.dataDoc[this.props.fieldKey]); + } + + /** + * @returns a string array of the current attributes + */ + @computed get currentFacets() { + return this.activeAttributes.map(attribute => StrCast(attribute.title)); + } + gatherFieldValues(dashboard: Doc, facetKey: string) { const childDocs = DocListCast((dashboard.data as any)[0].data); const valueSet = new Set<string>(); @@ -80,7 +156,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc subDocs.forEach((t) => { const facetVal = t[facetKey]; if (facetVal instanceof RichTextField) rtFields++; - facetVal && valueSet.add(Field.toString(facetVal as Field)); + facetVal !== undefined && valueSet.add(Field.toString(facetVal as Field)); const fieldKey = Doc.LayoutFieldKey(t); const annos = !Field.toString(Doc.LayoutField(t) as Field).includes("CollectionView"); DocListCast(t[annos ? fieldKey + "-annotations" : fieldKey]).forEach((newdoc) => newarray.push(newdoc)); @@ -92,13 +168,40 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc }); return { strings: Array.from(valueSet.keys()), rtFields }; } + + public removeFilter = (filterName: string) => { + console.log("remove filter"); + const targetDoc = FilterBox.targetDoc; + const filterDoc = targetDoc.currentFilter as Doc; + const attributes = DocListCast(filterDoc["data"]); + const found = attributes.findIndex(doc => doc.title === filterName); + if (found !== -1) { + (filterDoc["data"] as List<Doc>).splice(found, 1); + const docFilter = Cast(targetDoc._docFilters, listSpec("string")); + if (docFilter) { + let index: number; + while ((index = docFilter.findIndex(item => item.split(":")[0] === filterName)) !== -1) { + docFilter.splice(index, 1); + } + } + const docRangeFilters = Cast(targetDoc._docRangeFilters, listSpec("string")); + if (docRangeFilters) { + let index: number; + while ((index = docRangeFilters.findIndex(item => item.split(":")[0] === filterName)) !== -1) { + docRangeFilters.splice(index, 3); + } + } + } + } + /** * Responds to clicking the check box in the flyout menu */ facetClick = (facetHeader: string) => { - const targetDoc = CollectionDockingView.Instance.props.Document; - const found = DocListCast(this.dataDoc[this.props.fieldKey]).findIndex(doc => doc.title === facetHeader); + const targetDoc = FilterBox.targetDoc; + const found = this.activeAttributes.findIndex(doc => doc.title === facetHeader); if (found !== -1) { + // comment this bit out later once the x works in treeview (this.dataDoc[this.props.fieldKey] as List<Doc>).splice(found, 1); const docFilter = Cast(targetDoc._docFilters, listSpec("string")); if (docFilter) { @@ -169,28 +272,142 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc const script = ScriptField.MakeScript(scriptText, { this: Doc.name, heading: "string", checked: "string", containingTreeView: Doc.name }); return script ? () => script : undefined; } + + /** + * Sets whether filters are ANDed or ORed together + */ + @action + changeBool = (e: any) => { + (FilterBox.targetDoc.currentFilter as Doc).filterBoolean = e.currentTarget.value; + } + + /** + * Changes the value of the variable that determines whether the filters should apply to the dashboard or the collection + */ + @action + changeScope = (e: any) => { + FilterBox._filterScope = e.currentTarget.value; + } + + /** + * Changes whether to select matched or unmatched documents + */ + @action + changeMatch = (e: any) => { + this._filterMatch = e.currentTarget.value; + } + + @action + changeSelected = () => { + if (this._filterSelected) { + this._filterSelected = false; + SelectionManager.DeselectAll(); + } else { + this._filterSelected = true; + // helper method to select specified docs + } + } + + FilteringStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps | DocumentViewProps>, property: string) { + switch (property.split(":")[0]) { + case StyleProp.Decorations: + if (doc) { + return doc._viewType === CollectionViewType.Docking || (Doc.IsSystem(doc)) ? (null) : + <> + <div style={{ marginRight: "5px", fontSize: "10px" }}> + <select className="filterBox-selection"> + <option value="Is" key="Is">Is</option> + <option value="Is Not" key="Is Not">Is Not</option> + </select> + </div> + <div className="filterBox-treeView-close" onClick={e => this.removeFilter(StrCast(doc.title))}> + <FontAwesomeIcon icon={"times"} size="sm" /> + </div> + </>; + } + default: return DefaultStyleProvider(doc, props, property); + + } + } + suppressChildClick = () => ScriptField.MakeScript("")!; - @computed get flyoutpanel() { - return <div className="filterBox-flyout" style={{ width: `100%`, height: this.props.PanelHeight() - 30 }} onWheel={e => e.stopPropagation()}> - {this._allFacets.map(facet => <label className="filterBox-flyout-facet" key={`${facet}`} onClick={e => this.facetClick(facet)}> - <input type="checkbox" onChange={emptyFunction} checked={DocListCast(this.props.Document[this.props.fieldKey]).some(d => d.title === facet)} /> - <span className="checkmark" /> - {facet} - </label>)} - </div>; + + /** + * Adds a filterDoc to the list of saved filters + */ + saveFilter = () => { + Doc.AddDocToList(Doc.UserDoc(), "savedFilters", this.props.Document); } + + /** + * Changes the title of the filterDoc + */ + onTitleValueChange = (val: string) => { + this.props.Document.title = val || `FilterDoc for ${FilterBox.targetDoc.title}`; + return true; + } + + /** + * The flyout from which you can select a saved filter to apply + */ + @computed get flyoutPanel() { + return DocListCast(Doc.UserDoc().savedFilters).map(doc => { + return <> + <div className="filterBox-tempFlyout" onWheel={e => e.stopPropagation()} style={{ height: 50, border: "2px" }} onPointerDown={() => this.props.updateFilterDoc?.(doc)}> + {StrCast(doc.title)} + </div> + </>; + } + ); + } + setTreeHeight = (hgt: number) => { + this.layoutDoc._height = hgt + 140; // 50? need to add all the border sizes together. + } + + layoutHeight = () => this.layoutDoc[HeightSym](); render() { const facetCollection = this.props.Document; + // TODO uncomment the line below when the treeview x works + // const options = this._allFacets.filter(facet => this.currentFacets.indexOf(facet) === -1).map(facet => ({ value: facet, label: facet })); + const options = this._allFacets.map(facet => ({ value: facet, label: facet })); return this.props.dontRegisterView ? (null) : <div className="filterBox-treeView" style={{ width: "100%" }}> - <div className="filterBox-addFacet" style={{ width: "100%" }} onPointerDown={e => e.stopPropagation()}> - <Flyout anchorPoint={anchorPoints.LEFT_TOP} content={this.flyoutpanel}> - <div className="filterBox-addFacetButton"> - <FontAwesomeIcon icon={"edit"} size={"lg"} /> - <span className="filterBox-span">Choose Facets</span> - </div> - </Flyout> + + <div className="filterBox-title"> + <EditableView + key="editableView" + contents={this.props.Document.title} + height={24} + fontSize={15} + GetValue={() => StrCast(this.props.Document.title)} + SetValue={this.onTitleValueChange} + /> + </div> + + <div className="filterBox-select-bool"> + <select className="filterBox-selection" onChange={this.changeBool}> + <option value="AND" key="AND" selected={(FilterBox.targetDoc.currentFilter as Doc)?.filterBoolean === "AND"}>AND</option> + <option value="OR" key="OR" selected={(FilterBox.targetDoc.currentFilter as Doc)?.filterBoolean === "OR"}>OR</option> + </select> + <div className="filterBox-select-text">filters in </div> + <select className="filterBox-selection" onChange={this.changeScope}> + <option value="Current Dashboard" key="Current Dashboard" selected={"Current Dashboard" === FilterBox._filterScope}>Current Dashboard</option> + {/* <option value="Current Tab" key="Current Tab">Current Tab</option> */} + <option value="Current Collection" key="Current Collection" selected={"Current Collection" === FilterBox._filterScope}>Current Collection</option> + </select> </div> + + <div className="filterBox-select"> + <Select + placeholder="Add a filter..." + options={options} + isMulti={false} + onChange={val => this.facetClick((val as UserOptions).value)} + value={null} + closeMenuOnSelect={false} + /> + </div> + <div className="filterBox-tree" key="tree"> <CollectionTreeView Document={facetCollection} @@ -198,7 +415,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc fieldKey={this.props.fieldKey} CollectionView={undefined} disableDocBrushing={true} - setHeight={returnFalse} // if the tree view can trigger the height of the filter box to change, then this needs to be filled in. + setHeight={this.setTreeHeight} // if the tree view can trigger the height of the filter box to change, then this needs to be filled in. onChildClick={this.suppressChildClick} docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} @@ -206,7 +423,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc ContainingCollectionDoc={this.props.ContainingCollectionDoc} ContainingCollectionView={this.props.ContainingCollectionView} PanelWidth={this.props.PanelWidth} - PanelHeight={this.props.PanelHeight} + PanelHeight={this.layoutHeight} rootSelected={this.props.rootSelected} renderDepth={1} dropAction={this.props.dropAction} @@ -231,6 +448,42 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc removeDocument={returnFalse} addDocument={returnFalse} /> </div> + <div className="filterBox-bottom"> + {/* <div className="filterBox-select-matched"> + <input className="filterBox-select-box" type="checkbox" + onChange={this.changeSelected} /> + <div className="filterBox-select-text">select</div> + <select className="filterBox-selection" onChange={e => this.changeMatch(e)}> + <option value="matched" key="matched">matched</option> + <option value="unmatched" key="unmatched">unmatched</option> + </select> + <div className="filterBox-select-text">documents</div> + </div> */} + + <div style={{ display: "flex" }}> + <div className="filterBox-saveWrapper"> + <div className="filterBox-saveBookmark" + onPointerDown={this.saveFilter} + > + <div>SAVE</div> + </div> + </div> + <div className="filterBox-saveWrapper"> + <div className="filterBox-saveBookmark"> + <Flyout className="myFilters-flyout" anchorPoint={anchorPoints.TOP} content={this.flyoutPanel}> + <div>FILTERS</div> + </Flyout> + </div> + </div> + <div className="filterBox-saveWrapper"> + <div className="filterBox-saveBookmark" + onPointerDown={this.props.createNewFilterDoc} + > + <div>NEW</div> + </div> + </div> + </div> + </div> </div>; } } @@ -245,7 +498,7 @@ Scripting.addGlobal(function determineCheckedState(layoutDoc: Doc, facetHeader: } return undefined; }); -Scripting.addGlobal(function readFacetData(targetDoc: Doc, facetHeader: string) { +Scripting.addGlobal(function readFacetData(layoutDoc: Doc, facetHeader: string) { const allCollectionDocs = DocListCast(CollectionDockingView.Instance?.props.Document.allDocuments); const set = new Set<string>(); if (facetHeader === "tags") allCollectionDocs.forEach(child => Field.toString(child[facetHeader] as Field).split(":").forEach(key => set.add(key))); @@ -258,7 +511,7 @@ Scripting.addGlobal(function readFacetData(targetDoc: Doc, facetHeader: string) const doc = new Doc(); doc.system = true; doc.title = facetValue.toString(); - doc.target = targetDoc; + doc.target = layoutDoc; doc.facetHeader = facetHeader; doc.facetValue = facetValue; doc.treeViewChecked = ComputedField.MakeFunction("determineCheckedState(self.target, self.facetHeader, self.facetValue)"); |
