diff options
author | dg314 <david_grossman@brown.edu> | 2021-07-17 15:13:39 -0400 |
---|---|---|
committer | dg314 <david_grossman@brown.edu> | 2021-07-17 15:13:39 -0400 |
commit | 48dbde117728e4b36bae11f0f16a796059ecf7ee (patch) | |
tree | 90ed4c780c7afaa612e4a4c916121bd875ba6259 /src | |
parent | 4cb75250bacbd08f4ae2c6ef6b4a00472bc890c3 (diff) |
initial search panel
Diffstat (limited to 'src')
-rw-r--r-- | src/client/util/CurrentUserUtils.ts | 27 | ||||
-rw-r--r-- | src/client/views/MainView.tsx | 11 | ||||
-rw-r--r-- | src/client/views/StyleProvider.tsx | 2 | ||||
-rw-r--r-- | src/client/views/collections/CollectionSchemaView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/collections/SchemaTable.tsx | 3 | ||||
-rw-r--r-- | src/client/views/search/SearchBox.tsx | 117 |
6 files changed, 41 insertions, 121 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 12733e815..596ccd9a6 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -35,6 +35,8 @@ import { UndoManager } from "./UndoManager"; import { SnappingManager } from "./SnappingManager"; import { InkTool } from "../../fields/InkField"; import { computedFn } from "mobx-utils"; +import { CollectionSchemaBooleanCell } from "../views/collections/CollectionSchemaCells"; +import { Console } from "console"; export let resolvedPorts: { server: number, socket: number }; @@ -53,6 +55,7 @@ export class CurrentUserUtils { @observable public static GuestDashboard: Doc | undefined; @observable public static GuestMobile: Doc | undefined; @observable public static propertiesWidth: number = 0; + @observable public static searchPanelWidth: number = 0; // sets up the default User Templates - slideView, headerView static setupUserTemplateButtons(doc: Doc) { @@ -516,6 +519,7 @@ export class CurrentUserUtils { static async menuBtnDescriptions(doc: Doc) { return [ { title: "Dashboards", target: Cast(doc.myDashboards, Doc, null), icon: "desktop", click: 'selectMainMenu(self)' }, + { title: "Search", target: Cast(doc.mySearchPanel, Doc, null), icon: "search", click: 'selectMainMenu(self)' }, { title: "My Files", target: Cast(doc.myFilesystem, Doc, null), icon: "file", click: 'selectMainMenu(self)' }, { title: "Tools", target: Cast(doc.myTools, Doc, null), icon: "wrench", click: 'selectMainMenu(self)' }, { title: "Import", target: Cast(doc.myImportPanel, Doc, null), icon: "upload", click: 'selectMainMenu(self)' }, @@ -529,14 +533,15 @@ export class CurrentUserUtils { ]; } - static setupSearchPanel(doc: Doc) { + /*static setupSearchPanel(doc: Doc) { if (doc.mySearchPanelDoc === undefined) { doc.mySearchPanelDoc = new PrefetchProxy(Docs.Create.SearchDocument({ _width: 500, _height: 300, backgroundColor: "dimGray", ignoreClick: true, _searchDoc: true, childDropAction: "alias", _lockedPosition: true, _viewType: CollectionViewType.Schema, title: "sidebar search stack", system: true })) as any as Doc; } - } + }*/ + static async setupMenuPanel(doc: Doc, sharingDocumentId: string, linkDatabaseId: string) { if (doc.menuStack === undefined) { await this.setupSharingSidebar(doc, sharingDocumentId, linkDatabaseId); // sets up the right sidebar collection for mobile upload documents and sharing @@ -807,6 +812,7 @@ export class CurrentUserUtils { (doc.myRecentlyClosedDocs as any as Doc).contextMenuLabels = new List<string>(["Clear All"]); } } + static setupFilterDocs(doc: Doc) { // setup Filter item if (doc.currentFilter === undefined) { @@ -939,6 +945,21 @@ export class CurrentUserUtils { } } + // Search sidebar is where searches within the document are performed + static setupSearchSidebar(doc: Doc) { + if (doc.mySearchPanelDoc === undefined) { + doc.mySearchPanelDoc = new PrefetchProxy(Docs.Create.SearchDocument({ + _width: 500, _height: 300, backgroundColor: "dimGray", ignoreClick: true, _searchDoc: true, + childDropAction: "alias", _lockedPosition: true, _viewType: CollectionViewType.Schema, title: "sidebar search stack", system: true + })) as any as Doc; + } + if (doc.mySearchPanel === undefined) { + const searchPanelDoc = Cast(doc.mySearchPanelDoc, Doc, null); + //const newUpload = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("importDocument()"), toolTip: "Import External document", _stayInCollection: true, _hideContextMenu: true, title: "Import", icon: "upload", system: true }); + doc.mySearchPanel = new PrefetchProxy(Docs.Create.StackingDocument([searchPanelDoc], { title: "Search", _yMargin: 20, ignoreClick: true, _chromeHidden: true, _stayInCollection: true, _hideContextMenu: true, _lockedPosition: true, system: true })); + } + } + static setupClickEditorTemplates(doc: Doc) { if (doc["clickFuncs-child"] === undefined) { // to use this function, select it from the context menu of a collection. then edit the onChildClick script. Add two Doc variables: 'target' and 'thisContainer', then assign 'target' to some target collection. After that, clicking on any document in the initial collection will open it in the target @@ -1023,8 +1044,8 @@ export class CurrentUserUtils { this.setupDefaultIconTemplates(doc); // creates a set of icon templates triggered by the document deoration icon this.setupDocTemplates(doc); // sets up the template menu of templates this.setupImportSidebar(doc); + this.setupSearchSidebar(doc); // sets up the search sidebar this.setupActiveMobileMenu(doc); // sets up the current mobile menu for Dash Mobile - this.setupSearchPanel(doc); this.setupOverlays(doc); // documents in overlay layer this.setupDockedButtons(doc); // the bottom bar of font icons await this.setupSidebarButtons(doc); // the pop-out left sidebar of tools/panels diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 4eeb1fc95..bc9c6f4d2 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -180,8 +180,8 @@ export class MainView extends React.Component { const targClass = targets[0].className.toString(); if (SearchBox.Instance._searchbarOpen || SearchBox.Instance.open) { const check = targets.some((thing) => - (thing.className === "collectionSchemaView-searchContainer" || (thing as any)?.dataset.icon === "filter" || - thing.className === "collectionSchema-header-menuOptions")); + (thing.className === "collectionSchemaView-searchContainer" || (thing as any)?.dataset.icon === "filter" || + thing.className === "collectionSchema-header-menuOptions")); !check && SearchBox.Instance.resetSearch(true); } !targClass.includes("contextMenu") && ContextMenu.Instance.closeMenu(); @@ -388,7 +388,6 @@ export class MainView extends React.Component { SettingsManager.Instance.open(); break; case "Catalog": - SearchBox.Instance._searchFullDB = "My Stuff"; SearchBox.Instance.enter(undefined); break; case "Help": @@ -523,7 +522,7 @@ export class MainView extends React.Component { </svg>; } - @computed get search() { + /*@computed get search() { TraceMobx(); return <div className="mainView-searchPanel"> <SearchBox Document={CurrentUserUtils.MySearchPanelDoc} @@ -555,7 +554,7 @@ export class MainView extends React.Component { ContainingCollectionView={undefined} ContainingCollectionDoc={undefined} /> </div>; - } + }*/ @computed get invisibleWebBox() { // see note under the makeLink method in HypothesisUtils.ts return !DocumentLinksButton.invisibleWebDoc ? null : @@ -604,7 +603,7 @@ export class MainView extends React.Component { <GroupManager /> <GoogleAuthenticationManager /> <DocumentDecorations boundsLeft={this.leftOffset} boundsTop={this.topOffset} /> - {this.search} + {/*this.search*/} <CollectionMenu /> {LinkDescriptionPopup.descriptionPopup ? <LinkDescriptionPopup /> : null} {DocumentLinksButton.LinkEditorDocView ? <LinkMenu docView={DocumentLinksButton.LinkEditorDocView} changeFlyout={emptyFunction} /> : (null)} diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 9e61351c4..e670420d1 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -100,7 +100,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps const backColor = backgroundCol();// || (darkScheme() ? "black" : "white"); if (!backColor) return undefined; const nonAlphaColor = backColor.startsWith("#") ? (backColor as string).substring(0, 7) : - backColor.startsWith("rgba") ? backColor.replace(/,.[^,]*\)/, ")").replace("rgba", "rgb") : backColor + backColor.startsWith("rgba") ? backColor.replace(/,.[^,]*\)/, ")").replace("rgba", "rgb") : backColor; const col = Color(nonAlphaColor).rgb(); const colsum = (col.red() + col.green() + col.blue()); if (colsum / col.alpha() > 400 || col.alpha() < 0.25) return "black"; diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index b33c437a9..971dd5cbf 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -556,7 +556,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { style={{ overflow: this.props.scrollOverflow === true ? "scroll" : undefined, backgroundColor: "white", pointerEvents: this.props.Document._searchDoc !== undefined && !this.props.isContentActive() && !SnappingManager.GetIsDragging() ? "none" : undefined, - width: name === "collectionSchemaView-searchContainer" ? "auto" : this.props.PanelWidth() || "100%", height: this.props.PanelHeight() || "100%", position: "relative", + width: this.props.PanelWidth() || "100%", height: this.props.PanelHeight() || "100%", position: "relative", }} > <div className="collectionSchemaView-tableContainer" style={{ width: `calc(100% - ${this.previewWidth()}px)` }} diff --git a/src/client/views/collections/SchemaTable.tsx b/src/client/views/collections/SchemaTable.tsx index 0c69ee030..0175b0dc2 100644 --- a/src/client/views/collections/SchemaTable.tsx +++ b/src/client/views/collections/SchemaTable.tsx @@ -196,6 +196,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> { <div onClick={e => this.changeSorting(col)} style={{ width: 21, padding: 1, display: "inline", zIndex: 1, background: "inherit", cursor: "hand" }}> <FontAwesomeIcon icon={sortIcon} size="lg" /> </div> + {this.props.Document._chromeHidden || this.props.addDocument == returnFalse ? undefined : <div className="collectionSchemaView-addRow" onClick={this.createRow}>+ new</div>} </div>; return { @@ -559,7 +560,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> { onPointerDown={this.props.onPointerDown} onClick={this.props.onClick} onWheel={e => this.props.active(true) && e.stopPropagation()} onDrop={e => this.props.onDrop(e, {})} onContextMenu={this.onContextMenu} > {this.reactTable} - {this.props.Document._chromeHidden ? undefined : <div className="collectionSchemaView-addRow" onClick={this.createRow}>+ new</div>} + {this.props.Document._chromeHidden || this.props.addDocument == returnFalse ? undefined : <div className="collectionSchemaView-addRow" onClick={this.createRow}>+ new</div>} {!this._showDoc ? (null) : <div className="collectionSchemaView-documentPreview" ref="overlay" style={{ diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index b722868d6..740a28825 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -3,9 +3,9 @@ import { Tooltip } from '@material-ui/core'; import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { Doc, DocListCast, Field, Opt, DocListCastAsync } from '../../../fields/Doc'; +import { Doc, DocListCast, Field, Opt, DocListCastAsync, DataSym, HeightSym } from '../../../fields/Doc'; import { documentSchema } from "../../../fields/documentSchemas"; -import { Copy, Id } from '../../../fields/FieldSymbols'; +import { Copy, Id, ToString } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; import { createSchema, listSpec, makeInterface } from '../../../fields/Schema'; import { SchemaHeaderField } from '../../../fields/SchemaHeaderField'; @@ -52,8 +52,6 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc private docsforfilter: Doc[] | undefined = []; private realTotalResults: number = 0; private newsearchstring = ""; - private collectionRef = React.createRef<HTMLDivElement>(); - @observable _undoBackground: string | undefined = ""; @observable _icons: string[] = this._allIcons; @@ -116,62 +114,6 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc } }); - getFinalQuery(query: string): string { - //alters the query so it looks in the correct fields - //if this is true, th`en not all of the field boxes are checked - //TODO: data - const initialfilters = Cast(this.props.Document._docFilters, listSpec("string"), []); - - const filters: string[] = []; - - for (const initFilter of initialfilters) { - const fields = initFilter.split(":"); - if (fields[2] !== undefined) { - filters.push(fields[0]); - filters.push(fields[1]); - filters.push(fields[2]); - } - } - - const finalfilters: { [key: string]: string[] } = {}; - - for (let i = 0; i < filters.length; i = i++) { - const fields = filters[i].split(":"); - if (finalfilters[fields[0]] !== undefined) { - finalfilters[fields[0]].push(fields[1]); - } - else { - finalfilters[fields[0]] = [fields[1]]; - } - } - - for (const key in finalfilters) { - const values = finalfilters[key]; - if (values.length === 1) { - const mod = "_t:"; - const newWords: string[] = []; - const oldWords = values[0].split(" "); - oldWords.forEach((word, i) => i === 0 ? newWords.push(key + mod + word) : newWords.push("AND " + key + mod + word)); - query = `(${query}) AND (${newWords.join(" ")})`; - } - else { - for (let i = 0; i < values.length; i++) { - const mod = "_t:"; - const newWords: string[] = []; - const oldWords = values[i].split(" "); - oldWords.forEach((word, i) => i === 0 ? newWords.push(key + mod + word) : newWords.push("AND " + key + mod + word)); - const v = "(" + newWords.join(" ") + ")"; - if (i === 0) { - query = `(${query}) AND (${v}` + (values.length === 1 ? ")" : ""); - } - else query = query + " OR " + v + (i === values.length - 1 ? ")" : ""); - } - } - } - - return query.replace(/-\s+/g, ''); - } - @action filterDocsByType(docs: Doc[]) { const finalDocs: Doc[] = []; @@ -340,7 +282,6 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc this._results[index][1].push(...hlights); this._results[index][2].push(...line); } - })); this._curRequest = undefined; @@ -360,37 +301,6 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc return this._lockPromise; } - startDragCollection = async () => { - const res = await this.getAllResults(this.getFinalQuery(StrCast(this.layoutDoc._searchString))); - const filtered = this.filterDocsByType(res.docs); - const docs = filtered.map(doc => Doc.GetT(doc, "isPrototype", "boolean", true) ? Doc.MakeDelegate(doc) : Doc.MakeAlias(doc)); - let x = 0; - let y = 0; - for (const doc of docs.map(d => Doc.Layout(d))) { - doc.x = x; - doc.y = y; - const size = 200; - const aspect = Doc.NativeHeight(doc) / (Doc.NativeWidth(doc) || 1); - if (aspect > 1) { - doc._height = size; - doc._width = size / aspect; - } else if (aspect > 0) { - doc._width = size; - doc._height = size * aspect; - } else { - doc._width = size; - doc._height = size; - } - x += 250; - if (x > 1000) { - x = 0; - y += 300; - } - } - const headers = Cast(this.props.Document._schemaHeaders, listSpec(SchemaHeaderField), []).map(h => { const v = h[Copy](); v.color = "#f1efeb"; return v; }); - return Docs.Create.SchemaDocument(headers, DocListCast(this.dataDoc[this.fieldKey]), { _autoHeight: true, _viewType: CollectionViewType.Schema, title: StrCast(this.layoutDoc._searchString) }); - } - @action.bound openSearch(e: React.SyntheticEvent) { e.stopPropagation(); @@ -479,6 +389,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc render() { const myDashboards = DocListCast(CurrentUserUtils.MyDashboards.data); + return ( <div style={{ pointerEvents: "all" }} className="searchBox-container"> <div className="searchBox-bar" style={{ background: SearchBox.Instance._undoBackground }}> @@ -487,7 +398,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc {`${Doc.CurrentUserEmail}`} <div className="searchBox-logoff" onClick={() => window.location.assign(Utils.prepend("/logout"))}> Logoff - </div> + </div> </div> <div className="searchBox-lozenge" onClick={() => DocServer.UPDATE_SERVER_CACHE()}> {`UI project`} @@ -499,10 +410,10 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc </select> <div className="searchBox-dashboards" onClick={undoBatch(() => CurrentUserUtils.createNewDashboard(Doc.UserDoc()))}> New - </div> + </div> <div className="searchBox-dashboards" onClick={undoBatch(() => CurrentUserUtils.snapshotDashboard(Doc.UserDoc()))}> Snapshot - </div> + </div> </div> </div> <div className="searchBox-query" > @@ -511,24 +422,12 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc style={{ padding: 1, paddingLeft: 20, paddingRight: 60, color: "black", height: 20, width: 250 }} /> <div style={{ display: "flex", alignItems: "center" }}> <div style={{ position: "absolute", left: 10 }}> - <Tooltip title={<div className="dash-tooltip" >drag search results as collection</div>}> - <div ref={this.collectionRef}><FontAwesomeIcon onPointerDown={SetupDrag(this.collectionRef, () => StrCast(this.layoutDoc._searchString) ? this.startDragCollection() : undefined)} icon={"search"} size="lg" - style={{ cursor: "hand", color: "black", padding: 1, position: "relative" }} /></div> - </Tooltip> + <FontAwesomeIcon icon={"search"} size="lg" + style={{ color: "black", padding: 1, position: "relative" }} /> </div> <div style={{ position: "absolute", left: Doc.UserDoc().noviceMode ? 220 : 200, width: 30, zIndex: 9000, color: "grey", background: "white", }}> {`${this._results.length}` + " of " + `${this.realTotalResults}`} </div> - {Doc.UserDoc().noviceMode ? (null) : <div style={{ cursor: "default", left: 235, position: "absolute", }}> - <Tooltip title={<div className="dash-tooltip" >only display documents matching search</div>} > - <div> - <FontAwesomeIcon icon={"filter"} size="lg" - style={{ cursor: "hand", padding: 1, backgroundColor: this.filter ? "white" : "lightgray", color: this.filter ? "black" : "white" }} - onPointerDown={e => { e.stopPropagation(); SetupDrag(this.collectionRef, () => this.layoutDoc._searchString ? this.startDragCollection() : undefined); }} - onClick={action(() => this.setSearchFilter(this.currentSelectedCollection, this.filter ? undefined : this.docsforfilter))} /> - </div> - </Tooltip> - </div>} </div> </div > </div > |