diff options
author | Andy Rickert <andrew_rickert@brown.edu> | 2020-04-14 22:14:47 -0700 |
---|---|---|
committer | Andy Rickert <andrew_rickert@brown.edu> | 2020-04-14 22:14:47 -0700 |
commit | 5cad16a30c983690f5a2b9c14fa59779df933df3 (patch) | |
tree | 3d215765a47ffbf60fd0c1be5e46fae72350473f /src | |
parent | 1bbbb660e8f1f5e0165e4ab6d3d4ac1340cb2e23 (diff) |
adding linear doc wrapper to docs in seaarch menu
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/SearchDocBox.tsx | 432 | ||||
-rw-r--r-- | src/client/views/nodes/QueryBox.tsx | 2 | ||||
-rw-r--r-- | src/client/views/search/SearchBox.tsx | 97 |
3 files changed, 94 insertions, 437 deletions
diff --git a/src/client/views/SearchDocBox.tsx b/src/client/views/SearchDocBox.tsx deleted file mode 100644 index cd9666af8..000000000 --- a/src/client/views/SearchDocBox.tsx +++ /dev/null @@ -1,432 +0,0 @@ -import { library } from "@fortawesome/fontawesome-svg-core"; -import { faBullseye, faLink } from "@fortawesome/free-solid-svg-icons"; -import { action, computed, observable, runInAction } from "mobx"; -import { observer } from "mobx-react"; -//import "./SearchBoxDoc.scss"; -import { Doc, DocListCast } from "../../new_fields/Doc"; -import { Id } from "../../new_fields/FieldSymbols"; -import { BoolCast, Cast, NumCast, StrCast } from "../../new_fields/Types"; -import { returnFalse } from "../../Utils"; -import { Docs } from "../documents/Documents"; -import { SearchUtil } from "../util/SearchUtil"; -import { EditableView } from "./EditableView"; -import { ContentFittingDocumentView } from "./nodes/ContentFittingDocumentView"; -import { FieldView, FieldViewProps } from "./nodes/FieldView"; -import { FilterBox } from "./search/FilterBox"; -import { SearchItem } from "./search/SearchItem"; -import React = require("react"); - -export interface RecProps { - documents: { preview: Doc, similarity: number }[]; - node: Doc; - -} - -library.add(faBullseye, faLink); -export const keyPlaceholder = "Query"; - -@observer -export class SearchDocBox extends React.Component<FieldViewProps> { - - public static LayoutString(fieldKey: string) { return FieldView.LayoutString(SearchDocBox, fieldKey); } - - // @observable private _display: boolean = false; - @observable private _pageX: number = 0; - @observable private _pageY: number = 0; - @observable private _width: number = 0; - @observable private _height: number = 0; - @observable.shallow private _docViews: JSX.Element[] = []; - // @observable private _documents: { preview: Doc, score: number }[] = []; - private previewDocs: Doc[] = []; - - constructor(props: FieldViewProps) { - super(props); - this.editingMetadata = this.editingMetadata || false; - //SearchBox.Instance = this; - this.resultsScrolled = this.resultsScrolled.bind(this); - } - - - @computed - private get editingMetadata() { - return BoolCast(this.props.Document.editingMetadata); - } - - private set editingMetadata(value: boolean) { - this.props.Document.editingMetadata = value; - } - - static readonly buffer = 20; - - componentDidMount() { - runInAction(() => { - console.log("didit" - ); - this.query = StrCast(this.props.Document.searchText); - this.content = (Docs.Create.TreeDocument(DocListCast(Doc.GetProto(this.props.Document).data), { _width: 200, _height: 400, _chromeStatus: "disabled", title: `Search Docs:` + this.query })); - - }); - if (this.inputRef.current) { - this.inputRef.current.focus(); - runInAction(() => { - this._searchbarOpen = true; - }); - } - } - - @observable - private content: Doc | undefined; - - @action - updateKey = async (newKey: string) => { - this.query = newKey; - if (newKey.length > 1) { - let newdocs = await this.getAllResults(this.query); - let things = newdocs.docs - console.log(things); - console.log(this.content); - runInAction(() => { - this.content = Docs.Create.TreeDocument(things, { _width: 200, _height: 400, _chromeStatus: "disabled", title: `Search Docs:` + this.query }); - }); - console.log(this.content); - } - - - //this.keyRef.current && this.keyRef.current.setIsFocused(false); - //this.query.length === 0 && (this.query = keyPlaceholder); - return true; - } - - @computed - public get query() { - return StrCast(this.props.Document.query); - } - - public set query(value: string) { - this.props.Document.query = value; - } - - @observable private _searchString: string = ""; - @observable private _resultsOpen: boolean = false; - @observable private _searchbarOpen: boolean = false; - @observable private _results: [Doc, string[], string[]][] = []; - private _resultsSet = new Map<Doc, number>(); - @observable private _openNoResults: boolean = false; - @observable private _visibleElements: JSX.Element[] = []; - - private resultsRef = React.createRef<HTMLDivElement>(); - public inputRef = React.createRef<HTMLInputElement>(); - - private _isSearch: ("search" | "placeholder" | undefined)[] = []; - private _numTotalResults = -1; - private _endIndex = -1; - - - private _maxSearchIndex: number = 0; - private _curRequest?: Promise<any> = undefined; - - @action - getViews = async (doc: Doc) => { - const results = await SearchUtil.GetViewsOfDocument(doc); - let toReturn: Doc[] = []; - await runInAction(() => { - toReturn = results; - }); - return toReturn; - } - - @action.bound - onChange(e: React.ChangeEvent<HTMLInputElement>) { - this._searchString = e.target.value; - - this._openNoResults = false; - this._results = []; - this._resultsSet.clear(); - this._visibleElements = []; - this._numTotalResults = -1; - this._endIndex = -1; - this._curRequest = undefined; - this._maxSearchIndex = 0; - } - - enter = async (e: React.KeyboardEvent) => { - console.log(e.key); - if (e.key === "Enter") { - let newdocs = await this.getAllResults(this.query) - let things = newdocs.docs - console.log(things); - this.content = Docs.Create.TreeDocument(things, { _width: 200, _height: 400, _chromeStatus: "disabled", title: `Search Docs: "Results"` }); - - } - } - - - @action - submitSearch = async () => { - let query = this._searchString; - query = FilterBox.Instance.getFinalQuery(query); - this._results = []; - this._resultsSet.clear(); - this._isSearch = []; - this._visibleElements = []; - FilterBox.Instance.closeFilter(); - - //if there is no query there should be no result - if (query === "") { - return; - } - else { - this._endIndex = 12; - this._maxSearchIndex = 0; - this._numTotalResults = -1; - await this.getResults(query); - } - - runInAction(() => { - this._resultsOpen = true; - this._searchbarOpen = true; - this._openNoResults = true; - this.resultsScrolled(); - }); - } - - getAllResults = async (query: string) => { - return SearchUtil.Search(query, true, { fq: this.filterQuery, start: 0, rows: 10000000 }); - } - - private get filterQuery() { - const types = FilterBox.Instance.filterTypes; - const includeDeleted = FilterBox.Instance.getDataStatus(); - return "NOT baseProto_b:true" + (includeDeleted ? "" : " AND NOT deleted_b:true") + (types ? ` AND (${types.map(type => `({!join from=id to=proto_i}type_t:"${type}" AND NOT type_t:*) OR type_t:"${type}" OR type_t:"extension"`).join(" ")})` : ""); - } - - - private NumResults = 25; - private lockPromise?: Promise<void>; - getResults = async (query: string) => { - if (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, { fq: this.filterQuery, start: this._maxSearchIndex, rows: this.NumResults, hl: true, "hl.fl": "*" }).then(action(async (res: SearchUtil.DocSearchResult) => { - - // happens at the beginning - 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<string, string[]>(); - res.docs.map((doc, i) => lines.set(doc[Id], res.lines[i])); - const docs = await Promise.all(res.docs.map(async doc => (await Cast(doc.extendsDoc, Doc)) || doc)); - const highlights: typeof res.highlighting = {}; - docs.forEach((doc, index) => highlights[doc[Id]] = highlightList[index]); - const filteredDocs = FilterBox.Instance.filterDocsByType(docs); - runInAction(() => { - // this._results.push(...filteredDocs); - filteredDocs.forEach(doc => { - 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)) : []; - 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.NumResults; - - await this._curRequest; - } - this.resultsScrolled(); - res(); - }); - return this.lockPromise; - } - - collectionRef = React.createRef<HTMLSpanElement>(); - startDragCollection = async () => { - const res = await this.getAllResults(FilterBox.Instance.getFinalQuery(this._searchString)); - const filtered = FilterBox.Instance.filterDocsByType(res.docs); - // console.log(this._results) - const docs = filtered.map(doc => { - const isProto = Doc.GetT(doc, "isPrototype", "boolean", true); - if (isProto) { - return Doc.MakeDelegate(doc); - } else { - return 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 = NumCast(doc._nativeHeight) / NumCast(doc._nativeWidth, 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; - } - } - //return Docs.Create.TreeDocument(docs, { _width: 200, _height: 400, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` }); - return Docs.Create.QueryDocument(docs, { _width: 200, _height: 400, searchText: this._searchString, title: `Query Docs: "${this._searchString}"` }); - } - - @action.bound - openSearch(e: React.SyntheticEvent) { - e.stopPropagation(); - this._openNoResults = false; - FilterBox.Instance.closeFilter(); - this._resultsOpen = true; - this._searchbarOpen = true; - FilterBox.Instance._pointerTime = e.timeStamp; - } - - @action.bound - closeSearch = () => { - FilterBox.Instance.closeFilter(); - this.closeResults(); - this._searchbarOpen = false; - } - - @action.bound - closeResults() { - this._resultsOpen = false; - this._results = []; - this._resultsSet.clear(); - this._visibleElements = []; - this._numTotalResults = -1; - this._endIndex = -1; - this._curRequest = undefined; - } - - @action - resultsScrolled = (e?: React.UIEvent<HTMLDivElement>) => { - if (!this.resultsRef.current) return; - const scrollY = e ? e.currentTarget.scrollTop : this.resultsRef.current ? this.resultsRef.current.scrollTop : 0; - const itemHght = 53; - const startIndex = Math.floor(Math.max(0, scrollY / itemHght)); - const endIndex = Math.ceil(Math.min(this._numTotalResults - 1, startIndex + (this.resultsRef.current.getBoundingClientRect().height / itemHght))); - - this._endIndex = endIndex === -1 ? 12 : endIndex; - - if ((this._numTotalResults === 0 || this._results.length === 0) && this._openNoResults) { - this._visibleElements = [<div className="no-result">No Search Results</div>]; - return; - } - - if (this._numTotalResults <= this._maxSearchIndex) { - this._numTotalResults = this._results.length; - } - - // only hit right at the beginning - // visibleElements is all of the elements (even the ones you can't see) - else if (this._visibleElements.length !== this._numTotalResults) { - // undefined until a searchitem is put in there - this._visibleElements = Array<JSX.Element>(this._numTotalResults === -1 ? 0 : this._numTotalResults); - // indicates if things are placeholders - this._isSearch = Array<undefined>(this._numTotalResults === -1 ? 0 : this._numTotalResults); - } - - for (let i = 0; i < this._numTotalResults; 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? - if (i < startIndex || i > endIndex) { - if (this._isSearch[i] !== "placeholder") { - this._isSearch[i] = "placeholder"; - this._visibleElements[i] = <div className="searchBox-placeholder" key={`searchBox-placeholder-${i}`}>Loading...</div>; - } - } - else { - if (this._isSearch[i] !== "search") { - let result: [Doc, string[], string[]] | undefined = undefined; - if (i >= this._results.length) { - this.getResults(this._searchString); - if (i < this._results.length) result = this._results[i]; - if (result) { - const highlights = Array.from([...Array.from(new Set(result[1]).values())]); - this._visibleElements[i] = <SearchItem doc={result[0]} query={this._searchString} key={result[0][Id]} lines={result[2]} highlighting={highlights} />; - this._isSearch[i] = "search"; - } - } - else { - result = this._results[i]; - if (result) { - const highlights = Array.from([...Array.from(new Set(result[1]).values())]); - this._visibleElements[i] = <SearchItem doc={result[0]} query={this._searchString} key={result[0][Id]} lines={result[2]} highlighting={highlights} />; - this._isSearch[i] = "search"; - } - } - } - } - } - if (this._maxSearchIndex >= this._numTotalResults) { - this._visibleElements.length = this._results.length; - this._isSearch.length = this._results.length; - } - } - - @computed - get resFull() { return this._numTotalResults <= 8; } - - @computed - get resultHeight() { return this._numTotalResults * 70; } - - render() { - const isEditing = this.editingMetadata; - return ( - <div style={{ pointerEvents: "all" }}> - <ContentFittingDocumentView {...this.props} - Document={this.content} - rootSelected={returnFalse} - getTransform={this.props.ScreenToLocalTransform}> - </ContentFittingDocumentView> - <div - style={{ - position: "absolute", - right: 0, - width: 20, - height: 20, - background: "black", - pointerEvents: "all", - opacity: 1, - transition: "0.4s opacity ease", - zIndex: 99, - top: 0, - }} - title={"Add Metadata"} - onClick={action(() => { this.editingMetadata = !this.editingMetadata })} - /> - <div className="editableclass" onKeyPress={this.enter} style={{ opacity: isEditing ? 1 : 0, pointerEvents: isEditing ? "auto" : "none", transition: "0.4s opacity ease", position: "absolute", top: 0, left: 0, height: 20, width: "-webkit-fill-available" }}> - <EditableView - contents={this.query} - SetValue={this.updateKey} - GetValue={() => ""} - /> - </div> - </div > - ); - } - -}
\ No newline at end of file diff --git a/src/client/views/nodes/QueryBox.tsx b/src/client/views/nodes/QueryBox.tsx index 419768719..1b3f6280a 100644 --- a/src/client/views/nodes/QueryBox.tsx +++ b/src/client/views/nodes/QueryBox.tsx @@ -28,7 +28,7 @@ export class QueryBox extends DocAnnotatableComponent<FieldViewProps, QueryDocum render() { const dragging = !SelectionManager.GetIsDragging() ? "" : "-dragging"; return <div className={`queryBox${dragging}`} onWheel={(e) => e.stopPropagation()} > - <SearchBox id={this.props.Document[Id]} searchQuery={StrCast(this.dataDoc.searchQuery)} filterQuery={this.dataDoc.filterQuery} /> + <SearchBox id={this.props.Document[Id]} Document={this.props.Document} searchQuery={StrCast(this.dataDoc.searchQuery)} filterQuery={this.dataDoc.filterQuery} /> </div >; } }
\ No newline at end of file diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index bc77bff2e..f23525bdb 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -8,9 +8,9 @@ import * as rp from 'request-promise'; import { Doc } from '../../../new_fields/Doc'; import { Id } from '../../../new_fields/FieldSymbols'; import { Cast, NumCast, StrCast } from '../../../new_fields/Types'; -import { Utils } from '../../../Utils'; -import { Docs } from '../../documents/Documents'; -import { SetupDrag } from '../../util/DragManager'; +import { Utils, returnTrue, emptyFunction, returnFalse, emptyPath, returnOne } from '../../../Utils'; +import { Docs, DocumentOptions } from '../../documents/Documents'; +import { SetupDrag, DragManager } from '../../util/DragManager'; import { SearchUtil } from '../../util/SearchUtil'; import "./SearchBox.scss"; import { SearchItem } from './SearchItem'; @@ -20,11 +20,20 @@ import { DocumentType } from "../../documents/DocumentTypes"; import { DocumentView } from '../nodes/DocumentView'; import { SelectionManager } from '../../util/SelectionManager'; import { FilterQuery } from 'mongodb'; +import { CollectionLinearView } from '../collections/CollectionLinearView'; +import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils'; +import { CollectionDockingView } from '../collections/CollectionDockingView'; +import { ScriptField } from '../../../new_fields/ScriptField'; +import { PrefetchProxy } from '../../../new_fields/Proxy'; +import { List } from '../../../new_fields/List'; +import { faSearch, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote, faMusic, faLink, faChartBar, faGlobeAsia, faBan, faVideo, faCaretDown } from '@fortawesome/free-solid-svg-icons'; + library.add(faTimes); export interface SearchProps { id: string; + Document: Doc; searchQuery?: string; filterQuery?: filterData; } @@ -80,8 +89,14 @@ export class SearchBox extends React.Component<SearchProps> { SearchBox.Instance = this; this.resultsScrolled = this.resultsScrolled.bind(this); } - + @observable setupButtons =false; componentDidMount = () => { + console.log(this.setupButtons); + if (this.setupButtons==false){ + console.log("Yuh"); + this.setupDocTypeButtons(); + runInAction(()=>this.setupButtons==true); + } if (this.inputRef.current) { this.inputRef.current.focus(); runInAction(() => this._searchbarOpen = true); @@ -663,6 +678,79 @@ export class SearchBox extends React.Component<SearchProps> { @action.bound updateDataStatus() { this._deletedDocsStatus = !this._deletedDocsStatus; } + addButtonDoc = (doc: Doc) => Doc.AddDocToList(CurrentUserUtils.UserDocument.expandingButtons as Doc, "data", doc); + remButtonDoc = (doc: Doc) => Doc.RemoveDocFromList(CurrentUserUtils.UserDocument.expandingButtons as Doc, "data", doc); + moveButtonDoc = (doc: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => this.remButtonDoc(doc) && addDocument(doc); + + @computed get docButtons() { + const nodeBtns = this.props.Document.nodeButtons; + if (nodeBtns instanceof Doc) { + return <div id="hi"> + <CollectionLinearView + Document={nodeBtns} + DataDoc={undefined} + LibraryPath={emptyPath} + fieldKey={"data"} + dropAction={"alias"} + annotationsKey={""} + rootSelected={returnTrue} + bringToFront={emptyFunction} + select={emptyFunction} + active={returnFalse} + isSelected={returnFalse} + moveDocument={this.moveButtonDoc} + CollectionView={undefined} + addDocument={this.addButtonDoc} + addDocTab={returnFalse} + pinToPres={emptyFunction} + removeDocument={this.remButtonDoc} + onClick={undefined} + ScreenToLocalTransform={this.buttonBarXf} + ContentScaling={returnOne} + PanelWidth={this.flyoutWidthFunc} + PanelHeight={this.getContentsHeight} + renderDepth={0} + focus={emptyFunction} + whenActiveChanged={emptyFunction} + ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} /> + </div>; + } + return (null); + } + + setupDocTypeButtons() { + let doc = this.props.Document; + const ficon = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({ ...opts, dontDecorateSelection: true, dropAction: "alias", removeDropProperties: new List<string>(["dropAction"]), _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100 })) as any as Doc; + const blist = (opts: DocumentOptions, docs: Doc[]) => new PrefetchProxy(Docs.Create.LinearDocument(docs, { + ...opts, + _gridGap: 5, _xMargin: 5, _yMargin: 5, _height: 42, _width: 100, boxShadow: "0 0", dontDecorateSelection: true, forceActive: true, + dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), + backgroundColor: "black", treeViewPreventOpen: true, lockedPosition: true, _chromeStatus: "disabled", linearViewIsExpanded: true + })) as any as Doc; + + + doc.None = ficon({ onClick: undefined, title: "none button", icon: "ban" }); + doc.Music = ficon({ onClick: undefined, title: "mussic button", icon: "music" }); + doc.Col = ficon({ onClick: undefined, title: "col button", icon: "object-group" }); + doc.Hist = ficon({ onClick: undefined, title: "hist button", icon: "chart-bar" }); + doc.Image = ficon({ onClick: undefined, title: "image button", icon: "image" }); + doc.Link = ficon({ onClick: undefined, title: "link button", icon: "link" }); + doc.PDF = ficon({ onClick: undefined, title: "pdf button", icon: "file-pdf" }); + doc.TEXT = ficon({ onClick: undefined, title: "text button", icon: "sticky-note" }); + doc.Vid = ficon({ onClick: undefined, title: "vid button", icon: "video" }); + doc.Web = ficon({ onClick: undefined, title: "web button", icon: "globe-asia" }); + + let buttons = [doc.None as Doc, doc.Music as Doc, doc.Col as Doc, doc.Hist as Doc, + doc.Image as Doc, doc.Link as Doc, doc.PDF as Doc, doc.TEXT as Doc, doc.Vid as Doc, doc.Web as Doc]; + + const dragCreators = Docs.Create.MasonryDocument(CurrentUserUtils.setupCreatorButtons(doc), { + _width: 500, _autoHeight: true, columnWidth: 35, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled", title: "buttons", + dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), _yMargin: 5 + }); + doc.nodeButtons= dragCreators; + } + render() { return ( @@ -685,6 +773,7 @@ export class SearchBox extends React.Component<SearchProps> { </div> <div id={`node${this.props.id}`} className="filter-body" style={this._nodeStatus ? { borderTop: "grey 1px solid" } : { borderTop: "0px" }}> <IconBar /> + {this.docButtons} </div> <div className="filter-key" id={`key${this.props.id}`} style={this._keyStatus ? { borderTop: "grey 1px solid" } : { borderTop: "0px" }}> <div className="filter-keybar"> |