From c76598b7105e31e24ae771a839e63c27d787d3ed Mon Sep 17 00:00:00 2001 From: dg314 Date: Thu, 24 Jun 2021 04:54:33 -0400 Subject: removed search db option --- src/client/views/search/SearchBox.tsx | 44 ++++------------------------------- 1 file changed, 4 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 5c168d8a9..b722868d6 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -63,7 +63,6 @@ export class SearchBox extends ViewBoxBaseComponent { this.open = this._searchbarOpen = true; this.resultsScrolled(); @@ -289,7 +287,7 @@ export class SearchBox extends ViewBoxBaseComponent `NOT ({!join from=id to=proto_i}type_t:${type}) AND NOT type_t:${type}`).join(" AND ")}`; // fq: type_t:collection OR {!join from=id to=proto_i}type_t:collection q:text_t:hello @@ -471,39 +469,6 @@ export class SearchBox extends ViewBoxBaseComponent NumCast(this.layoutDoc._height); returnLength = () => Math.min(window.innerWidth, 51 + 205 * Cast(this.props.Document._schemaHeaders, listSpec(SchemaHeaderField), []).length); - @action - changeSearchScope = (scope: string) => { - this.docsforfilter = undefined; - this.setSearchFilter(this.currentSelectedCollection, undefined); - this._searchFullDB = scope; - this.dataDoc[this.fieldKey] = new List([]); - this.submitSearch(); - } - - @computed get scopeButtons() { - return
-
-
-
- -
-
- -
-
-
-
; - } - setSearchFilter = action((collectionView: { props: { Document: Doc } }, docsForFilter: Doc[] | undefined) => { if (collectionView) { const docFilters = Cast(this.props.Document._docFilters, listSpec("string"), null); @@ -564,7 +529,6 @@ export class SearchBox extends ViewBoxBaseComponent } - {this.scopeButtons} -- cgit v1.2.3-70-g09d2 From 4cb75250bacbd08f4ae2c6ef6b4a00472bc890c3 Mon Sep 17 00:00:00 2001 From: dg314 Date: Mon, 28 Jun 2021 15:25:41 -0400 Subject: db update --- src/client/views/GlobalKeyHandler.ts | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index cbaa706e0..d92cba3eb 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -225,7 +225,6 @@ export class KeyManager { PromiseValue(Cast(Doc.UserDoc()["tabs-button-tools"], Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv })); break; case "f": - SearchBox.Instance._searchFullDB = "My Stuff"; SearchBox.Instance.enter(undefined); break; case "o": -- cgit v1.2.3-70-g09d2 From 48dbde117728e4b36bae11f0f16a796059ecf7ee Mon Sep 17 00:00:00 2001 From: dg314 Date: Sat, 17 Jul 2021 15:13:39 -0400 Subject: initial search panel --- src/client/util/CurrentUserUtils.ts | 27 ++++- src/client/views/MainView.tsx | 11 +- src/client/views/StyleProvider.tsx | 2 +- .../views/collections/CollectionSchemaView.tsx | 2 +- src/client/views/collections/SchemaTable.tsx | 3 +- src/client/views/search/SearchBox.tsx | 117 ++------------------- 6 files changed, 41 insertions(+), 121 deletions(-) (limited to 'src') 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(["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 { ; } - @computed get search() { + /*@computed get search() { TraceMobx(); return
; - } + }*/ @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 { - {this.search} + {/*this.search*/} {LinkDescriptionPopup.descriptionPopup ? : null} {DocumentLinksButton.LinkEditorDocView ? : (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, props: Opt 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", }} >
{
this.changeSorting(col)} style={{ width: 21, padding: 1, display: "inline", zIndex: 1, background: "inherit", cursor: "hand" }}>
+ {this.props.Document._chromeHidden || this.props.addDocument == returnFalse ? undefined :
+ new
}
; return { @@ -559,7 +560,7 @@ export class SchemaTable extends React.Component { 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 :
+ new
} + {this.props.Document._chromeHidden || this.props.addDocument == returnFalse ? undefined :
+ new
} {!this._showDoc ? (null) :
(); - @observable _undoBackground: string | undefined = ""; @observable _icons: string[] = this._allIcons; @@ -116,62 +114,6 @@ export class SearchBox extends ViewBoxBaseComponent 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 { - 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
@@ -487,7 +398,7 @@ export class SearchBox extends ViewBoxBaseComponent window.location.assign(Utils.prepend("/logout"))}> Logoff -
+
DocServer.UPDATE_SERVER_CACHE()}> {`UI project`} @@ -499,10 +410,10 @@ export class SearchBox extends ViewBoxBaseComponent
CurrentUserUtils.createNewDashboard(Doc.UserDoc()))}> New -
+
CurrentUserUtils.snapshotDashboard(Doc.UserDoc()))}> Snapshot -
+
@@ -511,24 +422,12 @@ export class SearchBox extends ViewBoxBaseComponent
- drag search results as collection
}> -
StrCast(this.layoutDoc._searchString) ? this.startDragCollection() : undefined)} icon={"search"} size="lg" - style={{ cursor: "hand", color: "black", padding: 1, position: "relative" }} />
- +
{`${this._results.length}` + " of " + `${this.realTotalResults}`}
- {Doc.UserDoc().noviceMode ? (null) :
- only display documents matching search
} > -
- { e.stopPropagation(); SetupDrag(this.collectionRef, () => this.layoutDoc._searchString ? this.startDragCollection() : undefined); }} - onClick={action(() => this.setSearchFilter(this.currentSelectedCollection, this.filter ? undefined : this.docsforfilter))} /> -
- -
} -- cgit v1.2.3-70-g09d2 From 82c9db3e24baddeccafb67d2edc1a834f508f95a Mon Sep 17 00:00:00 2001 From: dg314 Date: Sat, 17 Jul 2021 15:33:43 -0400 Subject: search box --- src/client/views/search/SearchBox.tsx | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'src') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 740a28825..cc4590969 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -393,29 +393,6 @@ export class SearchBox extends ViewBoxBaseComponent
-
-
- {`${Doc.CurrentUserEmail}`} -
window.location.assign(Utils.prepend("/logout"))}> - Logoff -
-
-
DocServer.UPDATE_SERVER_CACHE()}> - {`UI project`} -
-
- -
CurrentUserUtils.createNewDashboard(Doc.UserDoc()))}> - New -
-
CurrentUserUtils.snapshotDashboard(Doc.UserDoc()))}> - Snapshot -
-
-
Date: Thu, 29 Jul 2021 15:12:03 -0400 Subject: search panel updates --- src/client/util/CurrentUserUtils.ts | 11 +- src/client/views/MainView.tsx | 6 +- src/client/views/search/SearchBox.scss | 173 ++++-------- src/client/views/search/SearchBox.tsx | 491 +++++++++++++++------------------ 4 files changed, 291 insertions(+), 390 deletions(-) (limited to 'src') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 596ccd9a6..31384da3b 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -947,17 +947,12 @@ 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, + if (doc.mySearchPanel === undefined) { + doc.mySearchPanel = new PrefetchProxy(Docs.Create.SearchDocument({ + 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) { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index bc9c6f4d2..0d957518b 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -178,12 +178,12 @@ export class MainView extends React.Component { const targets = document.elementsFromPoint(e.x, e.y); if (targets.length) { const targClass = targets[0].className.toString(); - if (SearchBox.Instance._searchbarOpen || SearchBox.Instance.open) { + /*if (SearchBox.Instance._resultsOpen) { const check = targets.some((thing) => (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(); !["timeline-menu-desc", "timeline-menu-item", "timeline-menu-input"].includes(targClass) && TimelineMenu.Instance.closeMenu(); } @@ -192,7 +192,7 @@ export class MainView extends React.Component { initEventListeners = () => { window.addEventListener("drop", e => e.preventDefault(), false); // prevent default behavior of navigating to a new web page window.addEventListener("dragover", e => e.preventDefault(), false); - document.addEventListener("pointermove", action(e => SearchBox.Instance._undoBackground = UndoManager.batchCounter ? "#000000a8" : undefined)); + //document.addEventListener("pointermove", action(e => SearchBox.Instance._undoBackground = UndoManager.batchCounter ? "#000000a8" : undefined)); document.addEventListener("pointerdown", this.globalPointerDown); document.addEventListener("click", (e: MouseEvent) => { if (!e.cancelBubble) { diff --git a/src/client/views/search/SearchBox.scss b/src/client/views/search/SearchBox.scss index 4f5b7e41a..f8e994da7 100644 --- a/src/client/views/search/SearchBox.scss +++ b/src/client/views/search/SearchBox.scss @@ -2,141 +2,84 @@ @import "./NaviconButton.scss"; .searchBox-container { - display: flex; - flex-direction: column; width: 100%; height: 100%; - position: relative; font-size: 10px; line-height: 1; - overflow-y: auto; - overflow-x: visible; - background: lightgrey; - overflow: visible; + background: none; z-index: 1000; + padding: 0px; + cursor: default; .searchBox-bar { - height: $searchpanel-height; + width: 100%; + height: 35px; display: flex; justify-content: center; align-items: center; - background-color: black; + background-color: none; + padding: 5px; - .searchBox-lozenges { - position: absolute; - left: 15; - display: flex; - - .searchBox-lozenge-user, - .searchBox-lozenge-dashboard, - .searchBox-lozenge { - height: 18px; - padding: 4px; - margin-right: 5px; - display: flex; - align-items: center; - border: grey 1px solid; - .searchBox-logoff, - .searchBox-dashboards { - border-radius: 3px; - background: olivedrab; - color: white; - display: none; - margin-left: 5px; - padding: 1px 2px 1px 2px; - cursor: pointer; - } - .searchBox-logoff { - background: red; - } - - .searchBox-dashSelect{ - border: none; - background-color: transparent; + .searchBox-type { + display: block; + width: 50px; + outline: none; + padding: 1px 5px 1px 5px; + color: black; + height: 25px; + border: 1px solid black; + } - &:hover { - cursor: pointer; - } - } - } - .searchBox-lozenge-user:hover { - .searchBox-logoff { - display:inline-block; - } - } - .searchBox-lozenge-dashboard:hover { - .searchBox-dashboards { - display:inline-block; - } - } + .searchBox-input { + display: block; + width: calc(100% - 50px); + outline: none; + padding: 1px 5px 1px 5px; + color: black; + height: 25px; + border: 1px solid black; } - .searchBox-query { - position: relative; + } + + .searchBox-results-container { + display: flex; + flex-direction: column; + width: 100%; + height: 100%; + justify-content: "center"; + + .searchBox-results-count { display: flex; - width: 450; + color: gray; + margin-left: 5px; } - .searchBox-barChild { + + .searchBox-results-scroll-view { + margin-top: 10px; + display: inline-block; + width: 100%; + height: calc(100% - 55px); + overflow-y: scroll; - &.searchBox-collection { - flex: 0 1 auto; - margin-left: 2px; - margin-right: 2px - } + .searchBox-results-scroll-view-result { + display: inline-block; + vertical-align: middle; + width: 100%; + height: 40px; + cursor: pointer; + font-size: 15px; + padding: 10px; - &.searchBox-input { - margin:5px; - border-radius:20px; - border:black; - display: block; - width: 130px; - -webkit-transition: width 0.4s; - transition: width 0.4s; - align-self: stretch; - outline:none; - &:focus { - width: 500px; - outline:none; + &.searchBox-results-scroll-view-result-selected { + background: gray; } - } - &.searchBox-filter { - align-self: stretch; - button{ - transform:none; - &:hover { - transform: none; - } - } - } - &.searchBox-submit { - margin-left: 2px; - margin-right: 2px - } - - &.searchBox-close { - color: $light-color; - max-height: $searchpanel-height; + .titletitle { + display: relative; + float: left; + left: 50px; + } } } - } -} - -.searchBox-results { - display: flex; - flex-direction: column; - top: 300px; - display: flex; - flex-direction: column; - height: 100%; - overflow: visible; - - .no-result { - width: 500px; - background: $light-color-secondary; - padding: 10px; - height: 50px; - text-transform: uppercase; - text-align: left; - font-weight: bold; } } \ No newline at end of file diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index cc4590969..374a754bf 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -3,7 +3,7 @@ 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, DataSym, HeightSym } from '../../../fields/Doc'; +import { Doc, DocListCast, Field, Opt, DocListCastAsync, DataSym, HeightSym, FieldsSym } from '../../../fields/Doc'; import { documentSchema } from "../../../fields/documentSchemas"; import { Copy, Id, ToString } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; @@ -26,6 +26,9 @@ import "./SearchBox.scss"; import { undoBatch } from "../../util/UndoManager"; import { DocServer } from "../../DocServer"; import { MainView } from "../MainView"; +import { DocumentManager } from "../../util/DocumentManager"; +import { CollectionSchemaBooleanCell } from "../collections/CollectionSchemaCells"; +import { transpileModule } from "typescript"; export const searchSchema = createSchema({ Document: Doc }); @@ -38,33 +41,18 @@ export class SearchBox extends ViewBoxBaseComponent; private _resultsSet = new Map(); private _inputRef = React.createRef(); - private _maxSearchIndex: number = 0; - private _curRequest?: Promise = undefined; private _disposers: { [name: string]: IReactionDisposer } = {}; private _blockedTypes = [DocumentType.PRESELEMENT, DocumentType.KVP, DocumentType.FILTER, DocumentType.SEARCH, DocumentType.SEARCHITEM, DocumentType.FONTICON, DocumentType.BUTTON, DocumentType.SCRIPTING]; - private docsforfilter: Doc[] | undefined = []; - private realTotalResults: number = 0; - private newsearchstring = ""; - - @observable _undoBackground: string | undefined = ""; + @observable _searchString = ""; + @observable _docTypeString = "all"; @observable _icons: string[] = this._allIcons; @observable _results: [Doc, string[], string[]][] = []; - @observable _visibleElements: JSX.Element[] = []; - @observable _visibleDocuments: Doc[] = []; + @observable _selectedResult: Doc | undefined = undefined; @observable _deletedDocsStatus: boolean = false; @observable _onlyAliases: boolean = true; - @observable _searchbarOpen = false; - @observable _noResults = ""; - @observable _pageStart = 0; - @observable open = false; - @observable children = 0; @computed get filter() { return this._results?.length && (this.currentSelectedCollection?.props.Document._searchFilterDocs || this.currentSelectedCollection?.props.Document._docFilters); } constructor(props: any) { @@ -76,8 +64,6 @@ export class SearchBox extends ViewBoxBaseComponent this.props.Document._docFilters, - (filters: any) => this.setSearchFilter(this.currentSelectedCollection, !this.filter ? undefined : this.docsforfilter)); }); componentWillUnmount() { @@ -86,32 +72,25 @@ export class SearchBox extends ViewBoxBaseComponent) => { - this.newsearchstring = e.target.value; - if (e.target.value === "") { - console.log("Reset start"); - this.docsforfilter = undefined; - this.setSearchFilter(this.currentSelectedCollection, undefined); - this.resetSearch(false); - - this.open = false; - this._results = []; - this._resultsSet.clear(); - this._visibleElements = []; - this._numTotalResults = -1; - this._endIndex = -1; - this._curRequest = undefined; - this._maxSearchIndex = 0; - } + onInputChange = action((e: React.ChangeEvent) => { + this._searchString = e.target.value; + this.submitSearch(); }); - enter = action((e: React.KeyboardEvent | undefined) => { + onSelectChange = action((e: React.ChangeEvent) => { + this._docTypeString = e.target.value; + this.submitSearch(); + }); + + /*enter = action((e: React.KeyboardEvent | undefined) => { if (!e || e.key === "Enter") { - this.layoutDoc._searchString = this.newsearchstring; - this._pageStart = 0; - this.open = true; this.submitSearch(); } + });*/ + + onResultClick = action((doc: Doc) => { + this.selectElement(doc); + this._selectedResult = doc; }); @action @@ -126,21 +105,6 @@ export class SearchBox extends ViewBoxBaseComponent void) { - let newarray: Doc[] = []; - while (docs.length > 0) { - newarray = []; - await Promise.all(docs.filter(d => d).map(async d => { - const fieldKey = Doc.LayoutFieldKey(d); - const annos = !Field.toString(Doc.LayoutField(d) as Field).includes("CollectionView"); - const data = d[annos ? fieldKey + "-annotations" : fieldKey]; - const docs = await DocListCastAsync(data); - docs && newarray.push(...docs); - func(d); - })); - docs = newarray; - } - } static foreachRecursiveDoc(docs: Doc[], func: (doc: Doc) => void) { let newarray: Doc[] = []; while (docs.length > 0) { @@ -172,15 +136,7 @@ export class SearchBox extends ViewBoxBaseComponent r[0]); - this.setSearchFilter(selectedCollection, this.filter && found.length ? this.docsforfilter : undefined); - this._numTotalResults = found.length; - this.realTotalResults = found.length; } - else { - this._noResults = "No collection selected :("; - } - } static documentKeys(doc: Doc) { @@ -197,246 +153,253 @@ export class SearchBox extends ViewBoxBaseComponent { - this.resetSearch(false); - - //this.props.Document._docFilters = new List(); - this._noResults = ""; + this.resetSearch(); this.dataDoc[this.fieldKey] = new List([]); - this.children = 0; - let query = StrCast(this.layoutDoc._searchString); + let query = StrCast(this._searchString); Doc.SetSearchQuery(query); this._results = []; this._resultsSet.clear(); - this._visibleElements = []; - this._visibleDocuments = []; if (query) { - this._endIndex = 12; - this._maxSearchIndex = 0; - this._numTotalResults = -1; this.searchCollection(query); - runInAction(() => { - this.open = this._searchbarOpen = true; - this.resultsScrolled(); - }); } } - getAllResults = async (query: string) => { - return SearchUtil.Search(query, true, { fq: this.filterQuery, start: 0, rows: 10000000 }); - } + resetSearch = action(() => { + this._results.forEach(result => { + Doc.UnBrushDoc(result[0]); + Doc.ClearSearchMatches(); + }); + }); - private get filterQuery() { - const baseExpr = "NOT system_b:true"; - const authorExpr = undefined; - const includeDeleted = this._deletedDocsStatus ? "" : " NOT deleted_b:true"; - const typeExpr = this._onlyAliases ? "NOT {!join from=id to=proto_i}type_t:*" : `(type_t:* OR {!join from=id to=proto_i}type_t:*) ${this._blockedTypes.map(type => `NOT ({!join from=id to=proto_i}type_t:${type}) AND NOT type_t:${type}`).join(" AND ")}`; - // fq: type_t:collection OR {!join from=id to=proto_i}type_t:collection q:text_t:hello - return [baseExpr, authorExpr, includeDeleted, typeExpr].filter(q => q).join(" AND ").replace(/AND $/, ""); + selectElement = async (doc: Doc) => { + await DocumentManager.Instance.jumpToDocument(doc, true); // documents open in new tab instead of on right } - @computed get primarySort() { - const suffixMap = (type: ColumnType) => { - switch (type) { - case ColumnType.Date: return "_d"; - case ColumnType.String: return "_t"; - case ColumnType.Boolean: return "_b"; - case ColumnType.Number: return "_n"; + render() { + const results = this._results.map(result => { + var className = "searchBox-results-scroll-view-result"; + + if (this._selectedResult == result[0]) { + className += " searchBox-results-scroll-view-result-selected" } - }; - const headers = Cast(this.props.Document._schemaHeaders, listSpec(SchemaHeaderField), []); - return headers.reduce((p: Opt, header: SchemaHeaderField) => p || (header.desc !== undefined && suffixMap(header.type) ? (header.heading + suffixMap(header.type) + (header.desc ? " desc" : " asc")) : undefined), undefined); - } - searchDatabase = async (query: string) => { - this._lockPromise && (await this._lockPromise); - this._lockPromise = new Promise(async res => { - while (this._results.length <= this._endIndex && (this._numTotalResults === -1 || this._maxSearchIndex < this._numTotalResults)) { - this._curRequest = SearchUtil.Search(query, true, { onlyAliases: true, allowAliases: true, /*sort: this.primarySort,*/ fq: this.filterQuery, start: 0, rows: this._numResultsPerPage, hl: "on", "hl.fl": "*", }).then(action(async (res: SearchUtil.DocSearchResult) => { - // happens at the beginning - this.realTotalResults = res.numFound <= 0 ? 0 : res.numFound; - if (res.numFound !== this._numTotalResults && this._numTotalResults === -1) { - this._numTotalResults = res.numFound; - } - const highlighting = res.highlighting || {}; - const highlightList = res.docs.map(doc => highlighting[doc[Id]]); - const lines = new Map(); - res.docs.map((doc, i) => lines.set(doc[Id], res.lines[i])); - const docs = res.docs; - const highlights: typeof res.highlighting = {}; - docs.forEach((doc, index) => highlights[doc[Id]] = highlightList[index]); - const filteredDocs = this.filterDocsByType(docs); - - runInAction(() => filteredDocs.forEach((doc, i) => { - const index = this._resultsSet.get(doc); - const highlight = highlights[doc[Id]]; - const line = lines.get(doc[Id]) || []; - const hlights = highlight ? Object.keys(highlight).map(key => key.substring(0, key.length - 2)).filter(k => k) : []; - // if (this.findCommonElements(hlights)) { - // } - if (index === undefined) { - this._resultsSet.set(doc, this._results.length); - this._results.push([doc, hlights, line]); - } else { - this._results[index][1].push(...hlights); - this._results[index][2].push(...line); - } - })); - - this._curRequest = undefined; - })); - this._maxSearchIndex += this._numResultsPerPage; - - await this._curRequest; + if (this._docTypeString == "all" || this._docTypeString == result[0].type) { + return (
this.onResultClick(result[0])} className={className}>
{result[0].title}
) } - this.resultsScrolled(); + return null; + }) - const selectedCollection = this.currentSelectedCollection;//SelectionManager.SelectedDocuments()[0]; - this.docsforfilter = this._results.map(r => r[0]); - this.setSearchFilter(selectedCollection, this.filter ? this.docsforfilter : undefined); - res(); - }); - return this._lockPromise; + results.filter(result => result) + + return ( +
+
+ + +
+
+
+ {`${results.length}` + " result" + (results.length == 1 ? "" : "s")} +
+
+ {results} +
+
+
+ ); } +} + + + +/* +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +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, DataSym, HeightSym, FieldsSym } from '../../../fields/Doc'; +import { documentSchema } from "../../../fields/documentSchemas"; +import { Copy, Id, ToString } from '../../../fields/FieldSymbols'; +import { List } from '../../../fields/List'; +import { createSchema, listSpec, makeInterface } from '../../../fields/Schema'; +import { SchemaHeaderField } from '../../../fields/SchemaHeaderField'; +import { Cast, NumCast, StrCast } from '../../../fields/Types'; +import { emptyFunction, returnFalse, returnZero, setupMoveUpEvents, Utils } from '../../../Utils'; +import { Docs } from '../../documents/Documents'; +import { DocumentType } from "../../documents/DocumentTypes"; +import { CurrentUserUtils } from "../../util/CurrentUserUtils"; +import { SetupDrag } from '../../util/DragManager'; +import { SearchUtil } from '../../util/SearchUtil'; +import { Transform } from '../../util/Transform'; +import { CollectionDockingView } from "../collections/CollectionDockingView"; +import { CollectionSchemaView, ColumnType } from "../collections/CollectionSchemaView"; +import { CollectionViewType } from '../collections/CollectionView'; +import { ViewBoxBaseComponent } from "../DocComponent"; +import { FieldView, FieldViewProps } from '../nodes/FieldView'; +import "./SearchBox.scss"; +import { undoBatch } from "../../util/UndoManager"; +import { DocServer } from "../../DocServer"; +import { MainView } from "../MainView"; +import { SelectionManager } from "../../util/SelectionManager"; +import { CollectionSchemaBooleanCell } from "../collections/CollectionSchemaCells"; +import { transpileModule } from "typescript"; +import { DocumentManager } from "../../util/DocumentManager"; + +export const searchSchema = createSchema({ Document: Doc }); + +type SearchBoxDocument = makeInterface<[typeof documentSchema, typeof searchSchema]>; +const SearchBoxDocument = makeInterface(documentSchema, searchSchema); + +@observer +export class SearchBox extends ViewBoxBaseComponent(SearchBoxDocument) { + public static LayoutString(fieldKey: string) { return FieldView.LayoutString(SearchBox, fieldKey); } + public static Instance: SearchBox; + + @observable _searchString = ""; + @observable _docTypeString = "all"; + @observable _results: [Doc, string[], string[]][] = []; + @observable _selectedResult: Doc | undefined = undefined; + @observable _deletedDocsStatus: boolean = false; + @observable _onlyAliases: boolean = true; - @action.bound - openSearch(e: React.SyntheticEvent) { - e.stopPropagation(); - this._results.forEach(result => Doc.BrushDoc(result[0])); + constructor(props: any) { + super(props); + SearchBox.Instance = this; } - resetSearch = action((close: boolean) => { - this._results.forEach(result => { - Doc.UnBrushDoc(result[0]); - Doc.ClearSearchMatches(); - }); - close && (this.open = this._searchbarOpen = false); + onInputChange = action((e: React.ChangeEvent) => { + this._searchString = e.target.value; + this.submitSearch(); }); - @action.bound - closeResults() { - this._results = []; - this._resultsSet.clear(); - this._visibleElements = []; - this._visibleDocuments = []; - this._numTotalResults = -1; - this._endIndex = -1; - this._curRequest = undefined; - } + onSelectChange = action((e: React.ChangeEvent) => { + this._docTypeString = e.target.value; + this.submitSearch(); + }); - @action - resultsScrolled = (e?: React.UIEvent) => { - this._endIndex = 30; - const headers = new Set(["title", "author", "text", "type", "data", "*lastModified", "context"]); + onResultClick = action((doc: Doc) => { + this.selectElement(doc); + this._selectedResult = doc; + }); - if (this._numTotalResults <= this._maxSearchIndex) { - this._numTotalResults = this._results.length; + static foreachRecursiveDoc(docs: Doc[], func: (doc: Doc) => void) { + const blockedTypes = [DocumentType.PRESELEMENT, DocumentType.KVP, DocumentType.FILTER, DocumentType.SEARCH, DocumentType.SEARCHITEM, DocumentType.FONTICON, DocumentType.BUTTON, DocumentType.SCRIPTING]; + let newarray: Doc[] = []; + while (docs.length > 0) { + newarray = []; + docs.filter(d => d).forEach(d => { + const dtype = StrCast(d.type, "string") as DocumentType; + if (dtype && !blockedTypes.includes(dtype)) { + const fieldKey = Doc.LayoutFieldKey(d); + const annos = !Field.toString(Doc.LayoutField(d) as Field).includes("CollectionView"); + const data = d[annos ? fieldKey + "-annotations" : fieldKey]; + data && newarray.push(...DocListCast(data)); + func(d); + } + }); + docs = newarray; } + } - // only hit right at the beginning - // visibleElements is all of the elements (even the ones you can't see) - if (this._visibleElements.length !== this._numTotalResults) { - // undefined until a searchitem is put in there - this._visibleElements = Array(this._numTotalResults === -1 ? 0 : this._numTotalResults); - this._visibleDocuments = Array(this._numTotalResults === -1 ? 0 : this._numTotalResults); - } - let max = this._numResultsPerPage; - max > this._results.length ? max = this._results.length : console.log(""); - for (let i = this._pageStart; i < max; i++) { - //if the index is out of the window then put a placeholder in - //should ones that have already been found get set to placeholders? - - let result: [Doc, string[], string[]] | undefined = undefined; - - result = this._results[i]; - if (result) { - const highlights = Array.from([...Array.from(new Set(result[1]).values())]); - const lines = new List(result[2]); - highlights.forEach((item) => headers.add(item)); - Doc.SetSearchMatch(result[0], { searchMatch: 1 }); - if (i < this._visibleDocuments.length) { - this._visibleDocuments[i] = result[0]; - Doc.BrushDoc(result[0]); - Doc.AddDocToList(this.dataDoc, this.props.fieldKey, result[0]); - this.children++; + @action + searchCollection(query: string) { + const selectedCollection = CollectionDockingView.Instance; + query = query.toLowerCase(); + + if (selectedCollection !== undefined) { + console.log("hello111") + // this._currentSelectedCollection = selectedCollection; + const docs = DocListCast(selectedCollection.dataDoc[Doc.LayoutFieldKey(selectedCollection.dataDoc)]); + const found: [Doc, string[], string[]][] = []; + SearchBox.foreachRecursiveDoc(docs, (doc: Doc) => { + console.log("HELLO") + if (this._docTypeString == "all" || this._docTypeString == doc.type) { + const hlights = new Set(); + SearchBox.documentKeys(doc).forEach(key => Field.toString(doc[key] as Field).toLowerCase().includes(query) && hlights.add(key)); + Array.from(hlights.keys()).length > 0 && found.push([doc, Array.from(hlights.keys()), []]); } - } - } - if (this.props.Document._schemaHeaders === undefined) { - this.props.Document._schemaHeaders = new List([new SchemaHeaderField("title", "#f1efeb")]); - } - if (this._maxSearchIndex >= this._numTotalResults) { - this._visibleElements.length = this._results.length; - this._visibleDocuments.length = this._results.length; + }); + + this._results = found; + //this.setSearchFilter(selectedCollection, this.filter && found.length ? this._docsforfilter : undefined); } } - getTransform = () => this.props.ScreenToLocalTransform().translate(-5, -65);// listBox padding-left and pres-box-cont minHeight - panelHeight = () => this.props.PanelHeight(); - selectElement = (doc: Doc) => { /* this.gotoDocument(this.childDocs.indexOf(doc), NumCasst(this.layoutDoc._itemIndex)); */ }; - returnHeight = () => NumCast(this.layoutDoc._height); - returnLength = () => Math.min(window.innerWidth, 51 + 205 * Cast(this.props.Document._schemaHeaders, listSpec(SchemaHeaderField), []).length); - - setSearchFilter = action((collectionView: { props: { Document: Doc } }, docsForFilter: Doc[] | undefined) => { - if (collectionView) { - const docFilters = Cast(this.props.Document._docFilters, listSpec("string"), null); - collectionView.props.Document._searchFilterDocs = docsForFilter?.length ? new List(docsForFilter) : undefined; - collectionView.props.Document._docFilters = docsForFilter?.length && docFilters?.length ? new List(docFilters) : undefined; + static documentKeys(doc: Doc) { + const keys: { [key: string]: boolean } = {}; + // bcz: ugh. this is untracked since otherwise a large collection of documents will blast the server for all their fields. + // then as each document's fields come back, we update the documents _proxies. Each time we do this, the whole schema will be + // invalidated and re-rendered. This workaround will inquire all of the document fields before the options button is clicked. + // then by the time the options button is clicked, all of the fields should be in place. If a new field is added while this menu + // is displayed (unlikely) it won't show up until something else changes. + //TODO Types + Doc.GetAllPrototypes(doc).map(proto => Object.keys(proto).forEach(key => keys[key] = false)); + return Array.from(Object.keys(keys)); + } + + @action + submitSearch = async () => { + Doc.ClearSearchMatches(); + this._results = []; + + this.dataDoc[this.fieldKey] = new List([]); + let query = StrCast(this._searchString); + Doc.SetSearchQuery(query); + this._results = []; + + if (query) { + this.searchCollection(query); } - }); + } + + selectElement = async (doc: Doc) => { + await DocumentManager.Instance.jumpToDocument(doc, true); // documents open in new tab instead of on right + } render() { - const myDashboards = DocListCast(CurrentUserUtils.MyDashboards.data); + const results = this._results.map(result => { + var className = "searchBox-results-scroll-view-result"; + + if (this._selectedResult == result[0]) { + className += " searchBox-results-scroll-view-result-selected" + } + + return (
this.onResultClick(result[0])} className={className}>
{result[0].title}
) + }) return (
-
-
- -
-
- -
-
- {`${this._results.length}` + " of " + `${this.realTotalResults}`} -
-
-
+
+ +
- {!this._searchbarOpen ? (null) : -
r?.focus()}> -
-
- window.innerWidth || this.children > 6 ? true : false} - focus={this.selectElement} - ScreenToLocalTransform={Transform.Identity} - /> -
setupMoveUpEvents(this, e, (e: PointerEvent, down: number[], delta: number[]) => { - this.props.Document._height = NumCast(this.props.Document._height) + delta[1]; - return false; - }, returnFalse, emptyFunction)} - > - -
-
-
+
+
+ {`${this._results.length}` + " result" + (this._results.length == 1 ? "" : "s")}
- } +
+ {results} +
+
); } -} \ No newline at end of file +}*/ \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 2ec093982c06965086326df73d365e1b54f6a2a2 Mon Sep 17 00:00:00 2001 From: dg314 Date: Wed, 4 Aug 2021 03:19:16 -0400 Subject: search panel updates --- src/client/util/CurrentUserUtils.ts | 27 ++++++----- src/client/views/GlobalKeyHandler.ts | 7 ++- src/client/views/MainView.tsx | 37 -------------- src/client/views/search/SearchBox.scss | 19 ++++++-- src/client/views/search/SearchBox.tsx | 89 +++++++++++++++++----------------- 5 files changed, 81 insertions(+), 98 deletions(-) (limited to 'src') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 31384da3b..734b96b1e 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -46,6 +46,7 @@ export class CurrentUserUtils { //TODO tfs: these should be temporary... private static mainDocId: string | undefined; + public static searchBtn: Doc; public static get id() { return this.curr_id; } public static get MainDocId() { return this.mainDocId; } public static set MainDocId(id: string | undefined) { this.mainDocId = id; } @@ -533,15 +534,6 @@ export class CurrentUserUtils { ]; } - /*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 @@ -562,10 +554,23 @@ export class CurrentUserUtils { _height: 60, watchedDocuments, onClick: ScriptField.MakeScript(click, { scriptContext: "any" }) - })); + }) + ); + + menuBtns.forEach(menuBtn => { + if (menuBtn.title == "Search") { + this.searchBtn = menuBtn; + } + }); // hack -- last button is assumed to be the userDoc menuBtns[menuBtns.length - 1].hidden = ComputedField.MakeFunction("IsNoviceMode()"); + menuBtns.forEach(menuBtn => { + if (menuBtn.title == "Search") { + doc.searchBtn = menuBtn + } + }) + doc.menuStack = new PrefetchProxy(Docs.Create.StackingDocument(menuBtns, { title: "menuItemPanel", childDropAction: "alias", @@ -950,7 +955,7 @@ export class CurrentUserUtils { if (doc.mySearchPanel === undefined) { doc.mySearchPanel = new PrefetchProxy(Docs.Create.SearchDocument({ backgroundColor: "dimGray", ignoreClick: true, _searchDoc: true, - childDropAction: "alias", _lockedPosition: true, _viewType: CollectionViewType.Schema, title: "sidebar search stack", system: true + childDropAction: "alias", _lockedPosition: true, _viewType: CollectionViewType.Schema, title: "Search Sidebar", system: true })) as any as Doc; } } diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index d92cba3eb..2a3cb36c7 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -27,7 +27,6 @@ import { LightboxView } from "./LightboxView"; import { MainView } from "./MainView"; import { DocumentLinksButton } from "./nodes/DocumentLinksButton"; import { AnchorMenu } from "./pdf/AnchorMenu"; -import { SearchBox } from "./search/SearchBox"; import { CurrentUserUtils } from "../util/CurrentUserUtils"; import { SettingsManager } from "../util/SettingsManager"; @@ -225,7 +224,11 @@ export class KeyManager { PromiseValue(Cast(Doc.UserDoc()["tabs-button-tools"], Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv })); break; case "f": - SearchBox.Instance.enter(undefined); + const searchBtn = Doc.UserDoc().searchBtn as Doc; + + if (searchBtn) { + MainView.Instance.selectMenu(searchBtn); + } break; case "o": const target = SelectionManager.Views()[0]; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 0d957518b..35222e91f 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -387,9 +387,6 @@ export class MainView extends React.Component { case "Settings": SettingsManager.Instance.open(); break; - case "Catalog": - SearchBox.Instance.enter(undefined); - break; case "Help": break; default: @@ -522,40 +519,6 @@ export class MainView extends React.Component { ; } - /*@computed get search() { - TraceMobx(); - return
- -
; - }*/ - @computed get invisibleWebBox() { // see note under the makeLink method in HypothesisUtils.ts return !DocumentLinksButton.invisibleWebDoc ? null :
diff --git a/src/client/views/search/SearchBox.scss b/src/client/views/search/SearchBox.scss index f8e994da7..e4d1ac6a3 100644 --- a/src/client/views/search/SearchBox.scss +++ b/src/client/views/search/SearchBox.scss @@ -22,17 +22,18 @@ .searchBox-type { display: block; - width: 50px; + width: 55px; outline: none; padding: 1px 5px 1px 5px; color: black; height: 25px; border: 1px solid black; + border-right: 0px; } .searchBox-input { display: block; - width: calc(100% - 50px); + width: calc(100% - 55px); outline: none; padding: 1px 5px 1px 5px; color: black; @@ -74,10 +75,20 @@ background: gray; } - .titletitle { + .searchBox-result-title { display: relative; float: left; - left: 50px; + width: calc(100% - 60px); + text-align: left; + } + + .searchBox-result-type { + font-size: 12px; + display: relative; + float: right; + width: 60px; + text-align: right; + color: #333; } } } diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 374a754bf..3cbb4b3b1 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -35,29 +35,30 @@ export const searchSchema = createSchema({ Document: Doc }); type SearchBoxDocument = makeInterface<[typeof documentSchema, typeof searchSchema]>; const SearchBoxDocument = makeInterface(documentSchema, searchSchema); +const selectValues = ["all", "rtf", "image", "pdf", "web", "video", "audio", "collection"] + @observer export class SearchBox extends ViewBoxBaseComponent(SearchBoxDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(SearchBox, fieldKey); } public static Instance: SearchBox; - private _allIcons: string[] = [DocumentType.INK, DocumentType.AUDIO, DocumentType.COL, DocumentType.IMG, DocumentType.LINK, DocumentType.PDF, DocumentType.RTF, DocumentType.VID, DocumentType.WEB]; private _resultsSet = new Map(); private _inputRef = React.createRef(); - private _disposers: { [name: string]: IReactionDisposer } = {}; - private _blockedTypes = [DocumentType.PRESELEMENT, DocumentType.KVP, DocumentType.FILTER, DocumentType.SEARCH, DocumentType.SEARCHITEM, DocumentType.FONTICON, DocumentType.BUTTON, DocumentType.SCRIPTING]; @observable _searchString = ""; @observable _docTypeString = "all"; - @observable _icons: string[] = this._allIcons; @observable _results: [Doc, string[], string[]][] = []; @observable _selectedResult: Doc | undefined = undefined; @observable _deletedDocsStatus: boolean = false; @observable _onlyAliases: boolean = true; - @computed get filter() { return this._results?.length && (this.currentSelectedCollection?.props.Document._searchFilterDocs || this.currentSelectedCollection?.props.Document._docFilters); } constructor(props: any) { super(props); SearchBox.Instance = this; + this._searchString = "reset_search"; + this.submitSearch(); + this._searchString = ""; + this.submitSearch(); } componentDidMount = action(() => { @@ -67,11 +68,9 @@ export class SearchBox extends ViewBoxBaseComponent disposer?.()); + this.resetSearch; } - @computed get currentSelectedCollection() { return CollectionDockingView.Instance; } - onInputChange = action((e: React.ChangeEvent) => { this._searchString = e.target.value; this.submitSearch(); @@ -79,32 +78,13 @@ export class SearchBox extends ViewBoxBaseComponent) => { this._docTypeString = e.target.value; - this.submitSearch(); }); - /*enter = action((e: React.KeyboardEvent | undefined) => { - if (!e || e.key === "Enter") { - this.submitSearch(); - } - });*/ - onResultClick = action((doc: Doc) => { this.selectElement(doc); this._selectedResult = doc; }); - @action - filterDocsByType(docs: Doc[]) { - const finalDocs: Doc[] = []; - docs.forEach(doc => { - const layoutresult = StrCast(doc.type, "string") as DocumentType; - if (layoutresult && !this._blockedTypes.includes(layoutresult) && this._icons.includes(layoutresult)) { - finalDocs.push(doc); - } - }); - return finalDocs; - } - static foreachRecursiveDoc(docs: Doc[], func: (doc: Doc) => void) { let newarray: Doc[] = []; while (docs.length > 0) { @@ -120,23 +100,39 @@ export class SearchBox extends ViewBoxBaseComponent { - const hlights = new Set(); - SearchBox.documentKeys(doc).forEach(key => Field.toString(doc[key] as Field).toLowerCase().includes(query) && hlights.add(key)); - Array.from(hlights.keys()).length > 0 && found.push([doc, Array.from(hlights.keys()), []]); + const dtype = StrCast(doc.type, "string") as DocumentType; + if (dtype && !blockedTypes.includes(dtype)) { + const hlights = new Set(); + SearchBox.documentKeys(doc).forEach(key => Field.toString(doc[key] as Field).toLowerCase().includes(query) && hlights.add(key)); + Array.from(hlights.keys()).length > 0 && this._results.push([doc, Array.from(hlights.keys()), []]); + } }); - - this._results = found; } + + this._results = Array.from(new Set(this._results)) + this._selectedResult = undefined } static documentKeys(doc: Doc) { @@ -155,7 +151,7 @@ export class SearchBox extends ViewBoxBaseComponent { this.resetSearch(); - this.dataDoc[this.fieldKey] = new List([]); + //this.dataDoc[this.fieldKey] = new List([]); let query = StrCast(this._searchString); Doc.SetSearchQuery(query); this._results = []; @@ -169,6 +165,7 @@ export class SearchBox extends ViewBoxBaseComponent { this._results.forEach(result => { Doc.UnBrushDoc(result[0]); + Doc.UnHighlightDoc(result[0]); Doc.ClearSearchMatches(); }); }); @@ -178,6 +175,8 @@ export class SearchBox extends ViewBoxBaseComponent { var className = "searchBox-results-scroll-view-result"; @@ -186,28 +185,30 @@ export class SearchBox extends ViewBoxBaseComponent this.onResultClick(result[0])} className={className}>
{result[0].title}
) + validResults++; + return (
this.onResultClick(result[0])} className={className}>
{result[0].title}
{SearchBox.formatType(StrCast(result[0].type))}
) } return null; }) - results.filter(result => result) + results.filter(result => result); + + const selectOptions = selectValues.map(value => { + return + }) return (
- +
- {`${results.length}` + " result" + (results.length == 1 ? "" : "s")} + {`${validResults}` + " result" + (validResults == 1 ? "" : "s")}
{results} -- cgit v1.2.3-70-g09d2 From d511c116330c3a125e6557aa5be70392aca4914b Mon Sep 17 00:00:00 2001 From: dg314 Date: Thu, 5 Aug 2021 16:38:00 -0400 Subject: comments --- src/client/views/MainView.tsx | 6 - .../views/collections/CollectionSchemaHeaders.tsx | 2 +- src/client/views/search/SearchBox.scss | 22 +- src/client/views/search/SearchBox.tsx | 382 +++++++++------------ 4 files changed, 177 insertions(+), 235 deletions(-) (limited to 'src') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 35222e91f..97c88930e 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -178,12 +178,6 @@ export class MainView extends React.Component { const targets = document.elementsFromPoint(e.x, e.y); if (targets.length) { const targClass = targets[0].className.toString(); - /*if (SearchBox.Instance._resultsOpen) { - const check = targets.some((thing) => - (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(); !["timeline-menu-desc", "timeline-menu-item", "timeline-menu-input"].includes(targClass) && TimelineMenu.Instance.closeMenu(); } diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx index 3b52e6408..c98dcd1d0 100644 --- a/src/client/views/collections/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/CollectionSchemaHeaders.tsx @@ -424,7 +424,7 @@ export class KeysDropdown extends React.Component { e.target.checked === true ? Doc.setDocFilter(this.props.Document, this._key, key, "check") : Doc.setDocFilter(this.props.Document, this._key, key, "remove"); e.target.checked === true ? this.closeResultsVisibility = "contents" : console.log(""); e.target.checked === true ? this.props.col.setColor("green") : this.updateFilter(); - e.target.checked === true && SearchBox.Instance.filter === true ? Doc.setDocFilter(docs[0], this._key, key, "check") : Doc.setDocFilter(docs[0], this._key, key, "remove"); + e.target.checked === true ? Doc.setDocFilter(docs[0], this._key, key, "check") : Doc.setDocFilter(docs[0], this._key, key, "remove"); }} checked={bool} /> diff --git a/src/client/views/search/SearchBox.scss b/src/client/views/search/SearchBox.scss index e4d1ac6a3..e7526dac8 100644 --- a/src/client/views/search/SearchBox.scss +++ b/src/client/views/search/SearchBox.scss @@ -66,13 +66,13 @@ display: inline-block; vertical-align: middle; width: 100%; - height: 40px; + height: 50px; cursor: pointer; font-size: 15px; - padding: 10px; + padding: 11px; &.searchBox-results-scroll-view-result-selected { - background: gray; + background: #999; } .searchBox-result-title { @@ -84,11 +84,25 @@ .searchBox-result-type { font-size: 12px; + margin-top: 6px; display: relative; float: right; width: 60px; text-align: right; - color: #333; + color: #222; + } + + .searchBox-result-keys { + font-size: 10px; + margin-top: 1px; + display: relative; + float: left; + width: 100%; + text-align: left; + color: #555; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } } } diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 3cbb4b3b1..8ef09aa56 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -27,66 +27,105 @@ import { undoBatch } from "../../util/UndoManager"; import { DocServer } from "../../DocServer"; import { MainView } from "../MainView"; import { DocumentManager } from "../../util/DocumentManager"; -import { CollectionSchemaBooleanCell } from "../collections/CollectionSchemaCells"; -import { transpileModule } from "typescript"; export const searchSchema = createSchema({ Document: Doc }); type SearchBoxDocument = makeInterface<[typeof documentSchema, typeof searchSchema]>; const SearchBoxDocument = makeInterface(documentSchema, searchSchema); -const selectValues = ["all", "rtf", "image", "pdf", "web", "video", "audio", "collection"] - +/** + * This is the SearchBox component. It represents the search box input and results in + * the search panel on the left side of the screen. + */ @observer export class SearchBox extends ViewBoxBaseComponent(SearchBoxDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(SearchBox, fieldKey); } public static Instance: SearchBox; - private _resultsSet = new Map(); private _inputRef = React.createRef(); + private _selectedCollection = CollectionDockingView.Instance; @observable _searchString = ""; @observable _docTypeString = "all"; - @observable _results: [Doc, string[], string[]][] = []; + @observable _results: [Doc, string[]][] = []; @observable _selectedResult: Doc | undefined = undefined; @observable _deletedDocsStatus: boolean = false; @observable _onlyAliases: boolean = true; + /** + * This is the constructor for the SearchBox class. + */ constructor(props: any) { super(props); SearchBox.Instance = this; - this._searchString = "reset_search"; - this.submitSearch(); - this._searchString = ""; - this.submitSearch(); } + /** + * This method is called when the SearchBox component is first mounted. When the user opens + * the search panel, the search input box is automatically selected. This allows the user to + * type in the search input box immediately, without needing clicking on it first. + */ componentDidMount = action(() => { if (this._inputRef.current) { this._inputRef.current.focus(); } }); + /** + * This method is called when the SearchBox component is about to be unmounted. When the user + * closes the search panel, the search and its results are reset. + */ componentWillUnmount() { - this.resetSearch; + this.resetSearch(); } + /** + * This method is called when the text in the search input box is modified by the user. The + * _searchString is updated to the new value of the text in the input box and submitSearch + * is called to update the search results accordingly. + * + * (Note: There is no longer a need to press enter to submit a search. Any update to the input + * causes a search to be submitted automatically.) + */ onInputChange = action((e: React.ChangeEvent) => { this._searchString = e.target.value; this.submitSearch(); }); + /** + * This method is called when the option in the select drop-down menu is changed. The + * _docTypeString is updated to the new value of the option in the drop-down menu. This + * is used to filter the results of the search to documents of a specific type. + * + * (Note: This doesn't affect the results array, so there is no need to submit a new + * search here. The results of the search on the _searchString query are simply filtered + * by type directly before rendering them.) + */ onSelectChange = action((e: React.ChangeEvent) => { this._docTypeString = e.target.value; }); + /** + * @param {Doc} doc - doc of the search result that has been clicked on + * + * This method is called when the user clicks on a search result. The _selectedResult is + * updated accordingly and the doc is highlighted with the selectElement method. + */ onResultClick = action((doc: Doc) => { this.selectElement(doc); this._selectedResult = doc; }); - static foreachRecursiveDoc(docs: Doc[], func: (doc: Doc) => void) { + /** + * @param {Doc[]} docs - docs to be searched through recursively + * @param {number, Doc => void} func - function to be called on each doc + * + * This method iterates through an array of docs and all docs within those docs, calling + * the function func on each doc. + */ + static foreachRecursiveDoc(docs: Doc[], func: (depth: number, doc: Doc) => void) { let newarray: Doc[] = []; + var depth = 0; while (docs.length > 0) { newarray = []; docs.filter(d => d).forEach(d => { @@ -94,12 +133,45 @@ export class SearchBox extends ViewBoxBaseComponent void} func - function to be called on each doc + * + * This method iterates asynchronously through an array of docs and all docs within those + * docs, calling the function func on each doc. + */ + static async foreachRecursiveDocAsync(docs: Doc[], func: (depth: number, doc: Doc) => void) { + let newarray: Doc[] = []; + var depth = 0; + while (docs.length > 0) { + newarray = []; + await Promise.all(docs.filter(d => d).map(async d => { + const fieldKey = Doc.LayoutFieldKey(d); + const annos = !Field.toString(Doc.LayoutField(d) as Field).includes("CollectionView"); + const data = d[annos ? fieldKey + "-annotations" : fieldKey]; + const docs = await DocListCastAsync(data); + docs && newarray.push(...docs); + func(depth, d); + })); + docs = newarray; + depth++; + } + } + + /** + * @param {String} type - string representing the type of a doc + * + * This method converts a doc type string of any length to a 3-letter doc type string in + * which the first letter is capitalized. This is used when displaying the type on the + * right side of each search result. + */ static formatType(type: String): String { if (type == "pdf") { return "PDF"; @@ -111,57 +183,75 @@ export class SearchBox extends ViewBoxBaseComponent { + if (this._selectedCollection !== undefined) { + const docs = DocListCast(this._selectedCollection.dataDoc[Doc.LayoutFieldKey(this._selectedCollection.dataDoc)]); + const docIDs: String[] = [] + SearchBox.foreachRecursiveDoc(docs, (depth: number, doc: Doc) => { const dtype = StrCast(doc.type, "string") as DocumentType; - if (dtype && !blockedTypes.includes(dtype)) { + if (dtype && !blockedTypes.includes(dtype) && !docIDs.includes(doc[Id]) && depth > 0) { const hlights = new Set(); SearchBox.documentKeys(doc).forEach(key => Field.toString(doc[key] as Field).toLowerCase().includes(query) && hlights.add(key)); - Array.from(hlights.keys()).length > 0 && this._results.push([doc, Array.from(hlights.keys()), []]); + blockedKeys.forEach(key => { + hlights.delete(key); + }) + Array.from(hlights.keys()).length > 0 && this._results.push([doc, Array.from(hlights.keys())]); } + docIDs.push(doc[Id]) }); } - - this._results = Array.from(new Set(this._results)) - this._selectedResult = undefined } + /** + * @param {Doc} doc - doc for which keys are returned + * + * This method returns a list of a document doc's keys. + */ static documentKeys(doc: Doc) { const keys: { [key: string]: boolean } = {}; - // bcz: ugh. this is untracked since otherwise a large collection of documents will blast the server for all their fields. - // then as each document's fields come back, we update the documents _proxies. Each time we do this, the whole schema will be - // invalidated and re-rendered. This workaround will inquire all of the document fields before the options button is clicked. - // then by the time the options button is clicked, all of the fields should be in place. If a new field is added while this menu - // is displayed (unlikely) it won't show up until something else changes. - //TODO Types Doc.GetAllPrototypes(doc).map(proto => Object.keys(proto).forEach(key => keys[key] = false)); return Array.from(Object.keys(keys)); } + /** + * This method submits a search with the _searchString as its query and updates + * the results array accordingly. + */ @action submitSearch = async () => { this.resetSearch(); - //this.dataDoc[this.fieldKey] = new List([]); let query = StrCast(this._searchString); Doc.SetSearchQuery(query); this._results = []; - this._resultsSet.clear(); if (query) { this.searchCollection(query); } } + /** + * This method resets the search by iterating through each result and removing all + * brushes and highlights. All search matches are cleared as well. + */ resetSearch = action(() => { this._results.forEach(result => { Doc.UnBrushDoc(result[0]); @@ -170,10 +260,32 @@ export class SearchBox extends ViewBoxBaseComponent { - await DocumentManager.Instance.jumpToDocument(doc, true); // documents open in new tab instead of on right + await DocumentManager.Instance.jumpToDocument(doc, true); + } + + /** + * This method returns a JSX list of the options in the select drop-down menu, which + * is used to filter the types of documents that appear in the search results. + */ + @computed + public get selectOptions() { + const selectValues = ["all", "rtf", "image", "pdf", "web", "video", "audio", "collection"] + + return selectValues.map(value => { + return + }) } + /** + * This method renders the search input box, select drop-down menu, and search results. + */ render() { var validResults = 0; @@ -186,7 +298,19 @@ export class SearchBox extends ViewBoxBaseComponent this.onResultClick(result[0])} className={className}>
{result[0].title}
{SearchBox.formatType(StrCast(result[0].type))}
) + return ( +
this.onResultClick(result[0])} className={className}> +
+ {result[0].title} +
+
+ {SearchBox.formatType(StrCast(result[0].type))} +
+
+ {result[1].join(", ")} +
+
+ ) } return null; @@ -194,15 +318,11 @@ export class SearchBox extends ViewBoxBaseComponent result); - const selectOptions = selectValues.map(value => { - return - }) - return (
@@ -217,190 +337,4 @@ export class SearchBox extends ViewBoxBaseComponent ); } -} - - - -/* -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -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, DataSym, HeightSym, FieldsSym } from '../../../fields/Doc'; -import { documentSchema } from "../../../fields/documentSchemas"; -import { Copy, Id, ToString } from '../../../fields/FieldSymbols'; -import { List } from '../../../fields/List'; -import { createSchema, listSpec, makeInterface } from '../../../fields/Schema'; -import { SchemaHeaderField } from '../../../fields/SchemaHeaderField'; -import { Cast, NumCast, StrCast } from '../../../fields/Types'; -import { emptyFunction, returnFalse, returnZero, setupMoveUpEvents, Utils } from '../../../Utils'; -import { Docs } from '../../documents/Documents'; -import { DocumentType } from "../../documents/DocumentTypes"; -import { CurrentUserUtils } from "../../util/CurrentUserUtils"; -import { SetupDrag } from '../../util/DragManager'; -import { SearchUtil } from '../../util/SearchUtil'; -import { Transform } from '../../util/Transform'; -import { CollectionDockingView } from "../collections/CollectionDockingView"; -import { CollectionSchemaView, ColumnType } from "../collections/CollectionSchemaView"; -import { CollectionViewType } from '../collections/CollectionView'; -import { ViewBoxBaseComponent } from "../DocComponent"; -import { FieldView, FieldViewProps } from '../nodes/FieldView'; -import "./SearchBox.scss"; -import { undoBatch } from "../../util/UndoManager"; -import { DocServer } from "../../DocServer"; -import { MainView } from "../MainView"; -import { SelectionManager } from "../../util/SelectionManager"; -import { CollectionSchemaBooleanCell } from "../collections/CollectionSchemaCells"; -import { transpileModule } from "typescript"; -import { DocumentManager } from "../../util/DocumentManager"; - -export const searchSchema = createSchema({ Document: Doc }); - -type SearchBoxDocument = makeInterface<[typeof documentSchema, typeof searchSchema]>; -const SearchBoxDocument = makeInterface(documentSchema, searchSchema); - -@observer -export class SearchBox extends ViewBoxBaseComponent(SearchBoxDocument) { - public static LayoutString(fieldKey: string) { return FieldView.LayoutString(SearchBox, fieldKey); } - public static Instance: SearchBox; - - @observable _searchString = ""; - @observable _docTypeString = "all"; - @observable _results: [Doc, string[], string[]][] = []; - @observable _selectedResult: Doc | undefined = undefined; - @observable _deletedDocsStatus: boolean = false; - @observable _onlyAliases: boolean = true; - - constructor(props: any) { - super(props); - SearchBox.Instance = this; - } - - onInputChange = action((e: React.ChangeEvent) => { - this._searchString = e.target.value; - this.submitSearch(); - }); - - onSelectChange = action((e: React.ChangeEvent) => { - this._docTypeString = e.target.value; - this.submitSearch(); - }); - - onResultClick = action((doc: Doc) => { - this.selectElement(doc); - this._selectedResult = doc; - }); - - static foreachRecursiveDoc(docs: Doc[], func: (doc: Doc) => void) { - const blockedTypes = [DocumentType.PRESELEMENT, DocumentType.KVP, DocumentType.FILTER, DocumentType.SEARCH, DocumentType.SEARCHITEM, DocumentType.FONTICON, DocumentType.BUTTON, DocumentType.SCRIPTING]; - let newarray: Doc[] = []; - while (docs.length > 0) { - newarray = []; - docs.filter(d => d).forEach(d => { - const dtype = StrCast(d.type, "string") as DocumentType; - if (dtype && !blockedTypes.includes(dtype)) { - const fieldKey = Doc.LayoutFieldKey(d); - const annos = !Field.toString(Doc.LayoutField(d) as Field).includes("CollectionView"); - const data = d[annos ? fieldKey + "-annotations" : fieldKey]; - data && newarray.push(...DocListCast(data)); - func(d); - } - }); - docs = newarray; - } - } - - @action - searchCollection(query: string) { - const selectedCollection = CollectionDockingView.Instance; - query = query.toLowerCase(); - - if (selectedCollection !== undefined) { - console.log("hello111") - // this._currentSelectedCollection = selectedCollection; - const docs = DocListCast(selectedCollection.dataDoc[Doc.LayoutFieldKey(selectedCollection.dataDoc)]); - const found: [Doc, string[], string[]][] = []; - SearchBox.foreachRecursiveDoc(docs, (doc: Doc) => { - console.log("HELLO") - if (this._docTypeString == "all" || this._docTypeString == doc.type) { - const hlights = new Set(); - SearchBox.documentKeys(doc).forEach(key => Field.toString(doc[key] as Field).toLowerCase().includes(query) && hlights.add(key)); - Array.from(hlights.keys()).length > 0 && found.push([doc, Array.from(hlights.keys()), []]); - } - }); - - this._results = found; - //this.setSearchFilter(selectedCollection, this.filter && found.length ? this._docsforfilter : undefined); - } - } - - static documentKeys(doc: Doc) { - const keys: { [key: string]: boolean } = {}; - // bcz: ugh. this is untracked since otherwise a large collection of documents will blast the server for all their fields. - // then as each document's fields come back, we update the documents _proxies. Each time we do this, the whole schema will be - // invalidated and re-rendered. This workaround will inquire all of the document fields before the options button is clicked. - // then by the time the options button is clicked, all of the fields should be in place. If a new field is added while this menu - // is displayed (unlikely) it won't show up until something else changes. - //TODO Types - Doc.GetAllPrototypes(doc).map(proto => Object.keys(proto).forEach(key => keys[key] = false)); - return Array.from(Object.keys(keys)); - } - - @action - submitSearch = async () => { - Doc.ClearSearchMatches(); - this._results = []; - - this.dataDoc[this.fieldKey] = new List([]); - let query = StrCast(this._searchString); - Doc.SetSearchQuery(query); - this._results = []; - - if (query) { - this.searchCollection(query); - } - } - - selectElement = async (doc: Doc) => { - await DocumentManager.Instance.jumpToDocument(doc, true); // documents open in new tab instead of on right - } - - render() { - const results = this._results.map(result => { - var className = "searchBox-results-scroll-view-result"; - - if (this._selectedResult == result[0]) { - className += " searchBox-results-scroll-view-result-selected" - } - - return (
this.onResultClick(result[0])} className={className}>
{result[0].title}
) - }) - - return ( -
-
- - -
-
-
- {`${this._results.length}` + " result" + (this._results.length == 1 ? "" : "s")} -
-
- {results} -
-
-
- ); - } -}*/ \ No newline at end of file +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From f4c61d4c92182dc6598a8b6c7460baa52c65ebdc Mon Sep 17 00:00:00 2001 From: dg314 Date: Thu, 5 Aug 2021 16:46:55 -0400 Subject: imports --- src/client/views/search/SearchBox.tsx | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 8ef09aa56..66012e3f4 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -1,32 +1,17 @@ -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Tooltip } from '@material-ui/core'; -import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; +import { action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { Doc, DocListCast, Field, Opt, DocListCastAsync, DataSym, HeightSym, FieldsSym } from '../../../fields/Doc'; +import { Doc, DocListCast, DocListCastAsync, Field } from '../../../fields/Doc'; import { documentSchema } from "../../../fields/documentSchemas"; -import { Copy, Id, ToString } from '../../../fields/FieldSymbols'; -import { List } from '../../../fields/List'; -import { createSchema, listSpec, makeInterface } from '../../../fields/Schema'; -import { SchemaHeaderField } from '../../../fields/SchemaHeaderField'; -import { Cast, NumCast, StrCast } from '../../../fields/Types'; -import { emptyFunction, returnFalse, returnZero, setupMoveUpEvents, Utils } from '../../../Utils'; -import { Docs } from '../../documents/Documents'; +import { Id } from '../../../fields/FieldSymbols'; +import { createSchema, makeInterface } from '../../../fields/Schema'; +import { StrCast } from '../../../fields/Types'; import { DocumentType } from "../../documents/DocumentTypes"; -import { CurrentUserUtils } from "../../util/CurrentUserUtils"; -import { SetupDrag } from '../../util/DragManager'; -import { SearchUtil } from '../../util/SearchUtil'; -import { Transform } from '../../util/Transform'; +import { DocumentManager } from "../../util/DocumentManager"; import { CollectionDockingView } from "../collections/CollectionDockingView"; -import { CollectionSchemaView, ColumnType } from "../collections/CollectionSchemaView"; -import { CollectionViewType } from '../collections/CollectionView'; import { ViewBoxBaseComponent } from "../DocComponent"; import { FieldView, FieldViewProps } from '../nodes/FieldView'; import "./SearchBox.scss"; -import { undoBatch } from "../../util/UndoManager"; -import { DocServer } from "../../DocServer"; -import { MainView } from "../MainView"; -import { DocumentManager } from "../../util/DocumentManager"; export const searchSchema = createSchema({ Document: Doc }); -- cgit v1.2.3-70-g09d2 From 576c74eb596d19a7dfbef832ad626f5fcc4b8c71 Mon Sep 17 00:00:00 2001 From: geireann Date: Thu, 5 Aug 2021 17:27:27 -0400 Subject: Update SearchBox.tsx --- src/client/views/search/SearchBox.tsx | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 66012e3f4..9150b2e39 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -222,6 +222,7 @@ export class SearchBox extends ViewBoxBaseComponent { + console.log("submit search"); this.resetSearch(); let query = StrCast(this._searchString); @@ -229,6 +230,7 @@ export class SearchBox extends ViewBoxBaseComponent Date: Sat, 14 Aug 2021 15:59:14 -0400 Subject: testing --- src/client/views/search/SearchBox.tsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 9150b2e39..b9b3e358d 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -9,6 +9,7 @@ import { StrCast } from '../../../fields/Types'; import { DocumentType } from "../../documents/DocumentTypes"; import { DocumentManager } from "../../util/DocumentManager"; import { CollectionDockingView } from "../collections/CollectionDockingView"; +import { CollectionSchemaBooleanCell } from '../collections/collectionSchema/CollectionSchemaCells'; import { ViewBoxBaseComponent } from "../DocComponent"; import { FieldView, FieldViewProps } from '../nodes/FieldView'; import "./SearchBox.scss"; @@ -28,7 +29,6 @@ export class SearchBox extends ViewBoxBaseComponent(); - private _selectedCollection = CollectionDockingView.Instance; @observable _searchString = ""; @observable _docTypeString = "all"; @@ -182,16 +182,21 @@ export class SearchBox extends ViewBoxBaseComponent { const dtype = StrCast(doc.type, "string") as DocumentType; + console.log("HELLO"); if (dtype && !blockedTypes.includes(dtype) && !docIDs.includes(doc[Id]) && depth > 0) { const hlights = new Set(); SearchBox.documentKeys(doc).forEach(key => Field.toString(doc[key] as Field).toLowerCase().includes(query) && hlights.add(key)); -- cgit v1.2.3-70-g09d2 From a8f73101fa9b254775665f0bd69a36d193bb9113 Mon Sep 17 00:00:00 2001 From: dg314 Date: Mon, 16 Aug 2021 16:51:50 -0400 Subject: small changes --- src/client/views/search/SearchBox.tsx | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index b9b3e358d..82eedd152 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -9,7 +9,6 @@ import { StrCast } from '../../../fields/Types'; import { DocumentType } from "../../documents/DocumentTypes"; import { DocumentManager } from "../../util/DocumentManager"; import { CollectionDockingView } from "../collections/CollectionDockingView"; -import { CollectionSchemaBooleanCell } from '../collections/collectionSchema/CollectionSchemaCells'; import { ViewBoxBaseComponent } from "../DocComponent"; import { FieldView, FieldViewProps } from '../nodes/FieldView'; import "./SearchBox.scss"; -- cgit v1.2.3-70-g09d2 From 44dc91e0157019a2ba216618b6d8761c73d21458 Mon Sep 17 00:00:00 2001 From: dg314 Date: Mon, 16 Aug 2021 16:52:21 -0400 Subject: testing --- src/client/views/search/SearchBox.tsx | 3 --- 1 file changed, 3 deletions(-) (limited to 'src') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 82eedd152..d424527b4 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -187,15 +187,12 @@ export class SearchBox extends ViewBoxBaseComponent { const dtype = StrCast(doc.type, "string") as DocumentType; - console.log("HELLO"); if (dtype && !blockedTypes.includes(dtype) && !docIDs.includes(doc[Id]) && depth > 0) { const hlights = new Set(); SearchBox.documentKeys(doc).forEach(key => Field.toString(doc[key] as Field).toLowerCase().includes(query) && hlights.add(key)); -- cgit v1.2.3-70-g09d2 From 9a11484bb0337b2b2c561190e4c9769a44471983 Mon Sep 17 00:00:00 2001 From: dg314 Date: Mon, 16 Aug 2021 16:55:12 -0400 Subject: minor changes --- src/client/views/search/SearchBox.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index d424527b4..41bdd526e 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -187,7 +187,7 @@ export class SearchBox extends ViewBoxBaseComponent Date: Mon, 16 Aug 2021 17:03:55 -0400 Subject: rootDoc bug fix --- src/client/views/search/SearchBox.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 41bdd526e..fe6b5d2b0 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -188,7 +188,7 @@ export class SearchBox extends ViewBoxBaseComponent { -- cgit v1.2.3-70-g09d2 From a634580c224c4113b6c8a4b83f17532e86b33225 Mon Sep 17 00:00:00 2001 From: dg314 Date: Mon, 16 Aug 2021 17:04:17 -0400 Subject: minor updates --- src/client/views/search/SearchBox.tsx | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index fe6b5d2b0..b07879674 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -223,7 +223,6 @@ export class SearchBox extends ViewBoxBaseComponent { - console.log("submit search"); this.resetSearch(); let query = StrCast(this._searchString); @@ -231,7 +230,6 @@ export class SearchBox extends ViewBoxBaseComponent