diff options
| author | Stanley Yip <stanley_yip@brown.edu> | 2020-01-08 13:47:29 -0500 |
|---|---|---|
| committer | Stanley Yip <stanley_yip@brown.edu> | 2020-01-08 13:47:29 -0500 |
| commit | abfa42b6f2cf863deee19aac19328a23687464cb (patch) | |
| tree | b481f23ffa7bccbde7a31de34f50d765b6b73162 /src/client/views/search | |
| parent | d8fc218f3481728f221ceacc60ac4bc553f8e295 (diff) | |
| parent | 19a71cb2788b9c1c8d8ced4af285bf91033ba626 (diff) | |
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web into pen
Diffstat (limited to 'src/client/views/search')
| -rw-r--r-- | src/client/views/search/FilterBox.tsx | 53 | ||||
| -rw-r--r-- | src/client/views/search/IconButton.tsx | 2 | ||||
| -rw-r--r-- | src/client/views/search/NaviconButton.tsx | 22 | ||||
| -rw-r--r-- | src/client/views/search/SearchBox.scss | 7 | ||||
| -rw-r--r-- | src/client/views/search/SearchBox.tsx | 51 | ||||
| -rw-r--r-- | src/client/views/search/SearchItem.scss | 108 | ||||
| -rw-r--r-- | src/client/views/search/SearchItem.tsx | 154 | ||||
| -rw-r--r-- | src/client/views/search/ToggleBar.tsx | 3 |
8 files changed, 166 insertions, 234 deletions
diff --git a/src/client/views/search/FilterBox.tsx b/src/client/views/search/FilterBox.tsx index 62f3aba4c..684f50766 100644 --- a/src/client/views/search/FilterBox.tsx +++ b/src/client/views/search/FilterBox.tsx @@ -62,15 +62,6 @@ export class FilterBox extends React.Component { super(props); FilterBox.Instance = this; } - - componentDidMount = () => { - document.addEventListener("pointerdown", (e) => { - if (!e.defaultPrevented && e.timeStamp !== this._pointerTime) { - SearchBox.Instance.closeSearch(); - } - }); - } - setupAccordion() { $('document').ready(function () { const acc = document.getElementsByClassName('filter-header'); @@ -79,7 +70,7 @@ export class FilterBox extends React.Component { acc[i].addEventListener("click", function (this: HTMLElement) { this.classList.toggle("active"); - var panel = this.nextElementSibling as HTMLElement; + const panel = this.nextElementSibling as HTMLElement; if (panel.style.maxHeight) { panel.style.overflow = "hidden"; panel.style.maxHeight = ""; @@ -96,7 +87,7 @@ export class FilterBox extends React.Component { } }); - let el = acc[i] as HTMLElement; + const el = acc[i] as HTMLElement; el.click(); } }); @@ -105,14 +96,14 @@ export class FilterBox extends React.Component { @action.bound minimizeAll() { $('document').ready(function () { - var acc = document.getElementsByClassName('filter-header'); + const acc = document.getElementsByClassName('filter-header'); // tslint:disable-next-line: prefer-for-of for (var i = 0; i < acc.length; i++) { - let classList = acc[i].classList; + const classList = acc[i].classList; if (classList.contains("active")) { acc[i].classList.toggle("active"); - var panel = acc[i].nextElementSibling as HTMLElement; + const panel = acc[i].nextElementSibling as HTMLElement; panel.style.overflow = "hidden"; panel.style.maxHeight = ""; } @@ -128,10 +119,10 @@ export class FilterBox extends React.Component { } basicRequireWords(query: string): string { - let oldWords = query.split(" "); - let newWords: string[] = []; + const oldWords = query.split(" "); + const newWords: string[] = []; oldWords.forEach(word => { - let newWrd = "+" + word; + const newWrd = "+" + word; newWords.push(newWrd); }); query = newWords.join(" "); @@ -140,7 +131,7 @@ export class FilterBox extends React.Component { } basicFieldFilters(query: string, type: string): string { - let oldWords = query.split(" "); + const oldWords = query.split(" "); let mod = ""; if (type === Keys.AUTHOR) { @@ -151,9 +142,9 @@ export class FilterBox extends React.Component { mod = " title_t:"; } - let newWords: string[] = []; + const newWords: string[] = []; oldWords.forEach(word => { - let newWrd = mod + word; + const newWrd = mod + word; newWords.push(newWrd); }); @@ -183,11 +174,11 @@ export class FilterBox extends React.Component { //gets all of the collections of all the docviews that are selected //if a collection is the only thing selected, search only in that collection (not its container) getCurCollections(): Doc[] { - let selectedDocs: DocumentView[] = SelectionManager.SelectedDocuments(); - let collections: Doc[] = []; + const selectedDocs: DocumentView[] = SelectionManager.SelectedDocuments(); + const collections: Doc[] = []; selectedDocs.forEach(async element => { - let layout: string = StrCast(element.props.Document.baseLayout); + const layout: string = StrCast(element.props.Document.layout); //checks if selected view (element) is a collection. if it is, adds to list to search through if (layout.indexOf("Collection") > -1) { //makes sure collections aren't added more than once @@ -229,14 +220,14 @@ export class FilterBox extends React.Component { } addCollectionFilter(query: string): string { - let collections: Doc[] = this.getCurCollections(); - let oldWords = query.split(" "); + const collections: Doc[] = this.getCurCollections(); + const oldWords = query.split(" "); - let collectionString: string[] = []; + const collectionString: string[] = []; collections.forEach(doc => { - let proto = doc.proto; - let protoId = (proto || doc)[Id]; - let colString: string = "{!join from=data_l to=id}id:" + protoId + " "; + const proto = doc.proto; + const protoId = (proto || doc)[Id]; + const colString: string = "{!join from=data_l to=id}id:" + protoId + " "; collectionString.push(colString); }); @@ -254,9 +245,9 @@ export class FilterBox extends React.Component { if (this._icons.length === 9) { return docs; } - let finalDocs: Doc[] = []; + const finalDocs: Doc[] = []; docs.forEach(doc => { - let layoutresult = Cast(doc.type, "string"); + const layoutresult = Cast(doc.type, "string"); if (layoutresult && this._icons.includes(layoutresult)) { finalDocs.push(doc); } diff --git a/src/client/views/search/IconButton.tsx b/src/client/views/search/IconButton.tsx index d2cfe7fad..f01508141 100644 --- a/src/client/views/search/IconButton.tsx +++ b/src/client/views/search/IconButton.tsx @@ -108,7 +108,7 @@ export class IconButton extends React.Component<IconButtonProps>{ @action.bound onClick = () => { - let newList: string[] = FilterBox.Instance.getIcons(); + const newList: string[] = FilterBox.Instance.getIcons(); if (!this._isSelected) { this._isSelected = true; diff --git a/src/client/views/search/NaviconButton.tsx b/src/client/views/search/NaviconButton.tsx index 3fa36b163..0fa4a0fca 100644 --- a/src/client/views/search/NaviconButton.tsx +++ b/src/client/views/search/NaviconButton.tsx @@ -4,7 +4,7 @@ import "./NaviconButton.scss"; import * as $ from 'jquery'; import { observable } from 'mobx'; -export interface NaviconProps{ +export interface NaviconProps { onClick(): void; } @@ -13,19 +13,21 @@ export class NaviconButton extends React.Component<NaviconProps> { @observable private _ref: React.RefObject<HTMLAnchorElement> = React.createRef(); componentDidMount = () => { - let that = this; - if(this._ref.current){this._ref.current.addEventListener("click", function(e) { - e.preventDefault(); - if(that._ref.current){ - that._ref.current.classList.toggle('active'); - return false; - } - });} + const that = this; + if (this._ref.current) { + this._ref.current.addEventListener("click", function (e) { + e.preventDefault(); + if (that._ref.current) { + that._ref.current.classList.toggle('active'); + return false; + } + }); + } } render() { return ( - <a id="hamburger-icon" href="#" ref = {this._ref} title="Menu"> + <a id="hamburger-icon" href="#" ref={this._ref} title="Menu"> <span className="line line-1"></span> <span className="line line-2"></span> <span className="line line-3"></span> diff --git a/src/client/views/search/SearchBox.scss b/src/client/views/search/SearchBox.scss index bc11604a5..0825580b7 100644 --- a/src/client/views/search/SearchBox.scss +++ b/src/client/views/search/SearchBox.scss @@ -69,13 +69,8 @@ top: 300px; display: flex; flex-direction: column; - // height: 560px; height: 100%; - // overflow: hidden; - // overflow-y: auto; - max-height: 560px; - overflow: hidden; - overflow-y: auto; + overflow: visible; .no-result { width: 500px; diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 899a35f48..dd1ac7421 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -8,18 +8,15 @@ import * as rp from 'request-promise'; import { Doc } from '../../../new_fields/Doc'; import { Id } from '../../../new_fields/FieldSymbols'; import { Cast, NumCast } from '../../../new_fields/Types'; -import { RouteStore } from '../../../server/RouteStore'; import { Utils } from '../../../Utils'; import { Docs } from '../../documents/Documents'; import { SetupDrag } from '../../util/DragManager'; import { SearchUtil } from '../../util/SearchUtil'; -import { MainView } from '../MainView'; import { FilterBox } from './FilterBox'; import "./FilterBox.scss"; import "./SearchBox.scss"; import { SearchItem } from './SearchItem'; import { IconBar } from './IconBar'; -import { string } from 'prop-types'; library.add(faTimes); @@ -86,11 +83,15 @@ export class SearchBox extends React.Component { this._maxSearchIndex = 0; } - enter = (e: React.KeyboardEvent) => { if (e.key === "Enter") { this.submitSearch(); } }; + enter = (e: React.KeyboardEvent) => { + if (e.key === "Enter") { + this.submitSearch(); + } + } public static async convertDataUri(imageUri: string, returnedFilename: string) { try { - let posting = Utils.prepend(RouteStore.dataUriToImage); + const posting = Utils.prepend("/uploadURI"); const returnedUri = await rp.post(posting, { body: { uri: imageUri, @@ -145,6 +146,7 @@ export class SearchBox extends React.Component { } + private NumResults = 25; private lockPromise?: Promise<void>; getResults = async (query: string) => { if (this.lockPromise) { @@ -152,7 +154,7 @@ export class SearchBox extends React.Component { } 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: 10, hl: true, "hl.fl": "*" }).then(action(async (res: SearchUtil.DocSearchResult) => { + 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) { @@ -166,7 +168,7 @@ export class SearchBox extends React.Component { 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]); - let filteredDocs = FilterBox.Instance.filterDocsByType(docs); + const filteredDocs = FilterBox.Instance.filterDocsByType(docs); runInAction(() => { // this._results.push(...filteredDocs); filteredDocs.forEach(doc => { @@ -186,7 +188,7 @@ export class SearchBox extends React.Component { this._curRequest = undefined; })); - this._maxSearchIndex += 10; + this._maxSearchIndex += this.NumResults; await this._curRequest; } @@ -198,8 +200,8 @@ export class SearchBox extends React.Component { collectionRef = React.createRef<HTMLSpanElement>(); startDragCollection = async () => { - let res = await this.getAllResults(FilterBox.Instance.getFinalQuery(this._searchString)); - let filtered = FilterBox.Instance.filterDocsByType(res.docs); + 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); @@ -232,8 +234,7 @@ export class SearchBox extends React.Component { y += 300; } } - return Docs.Create.FreeformDocument(docs, { width: 400, height: 400, panX: 175, panY: 175, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` }); - + return Docs.Create.TreeDocument(docs, { width: 200, height: 400, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` }); } @action.bound @@ -266,10 +267,10 @@ export class SearchBox extends React.Component { @action resultsScrolled = (e?: React.UIEvent<HTMLDivElement>) => { - let scrollY = e ? e.currentTarget.scrollTop : this.resultsRef.current ? this.resultsRef.current.scrollTop : 0; - let buffer = 4; - let startIndex = Math.floor(Math.max(0, scrollY / 70 - buffer)); - let endIndex = Math.ceil(Math.min(this._numTotalResults - 1, startIndex + (560 / 70) + buffer)); + 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; @@ -307,7 +308,7 @@ export class SearchBox extends React.Component { this.getResults(this._searchString); if (i < this._results.length) result = this._results[i]; if (result) { - let highlights = Array.from([...Array.from(new Set(result[1]).values())]).filter(v => v !== "search_string"); + 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"; } @@ -315,7 +316,7 @@ export class SearchBox extends React.Component { else { result = this._results[i]; if (result) { - let highlights = Array.from([...Array.from(new Set(result[1]).values())]).filter(v => v !== "search_string"); + 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"; } @@ -337,9 +338,9 @@ export class SearchBox extends React.Component { render() { return ( - <div className="searchBox-container"> + <div className="searchBox-container" onPointerDown={e => { e.stopPropagation(); e.preventDefault(); }}> <div className="searchBox-bar"> - <span className="searchBox-barChild searchBox-collection" onPointerDown={SetupDrag(this.collectionRef, this.startDragCollection)} ref={this.collectionRef} title="Drag Results as Collection"> + <span className="searchBox-barChild searchBox-collection" onPointerDown={SetupDrag(this.collectionRef, () => this._searchString ? this.startDragCollection() : undefined)} ref={this.collectionRef} title="Drag Results as Collection"> <FontAwesomeIcon icon="object-group" size="lg" /> </span> <input value={this._searchString} onChange={this.onChange} type="text" placeholder="Search..." id="search-input" ref={this.inputRef} @@ -347,13 +348,13 @@ export class SearchBox extends React.Component { style={{ width: this._searchbarOpen ? "500px" : "100px" }} /> <button className="searchBox-barChild searchBox-filter" title="Advanced Filtering Options" onClick={FilterBox.Instance.openFilter} onPointerDown={FilterBox.Instance.stopProp}><FontAwesomeIcon icon="ellipsis-v" color="white" /></button> </div> - {(this._numTotalResults > 0 || !this._searchbarOpen) ? (null) : - (<div className="searchBox-quickFilter" onPointerDown={this.openSearch}> - <div className="filter-panel"><IconBar /></div> - </div>)} + <div className="searchBox-quickFilter" onPointerDown={this.openSearch}> + <div className="filter-panel"><IconBar /></div> + </div> <div className="searchBox-results" onScroll={this.resultsScrolled} style={{ display: this._resultsOpen ? "flex" : "none", - height: this.resFull ? "560px" : this.resultHeight, overflow: this.resFull ? "auto" : "visible" + height: this.resFull ? "auto" : this.resultHeight, + overflow: "visibile" // this.resFull ? "auto" : "visible" }} ref={this.resultsRef}> {this._visibleElements} </div> diff --git a/src/client/views/search/SearchItem.scss b/src/client/views/search/SearchItem.scss index 9f12994c3..469f062b2 100644 --- a/src/client/views/search/SearchItem.scss +++ b/src/client/views/search/SearchItem.scss @@ -1,22 +1,14 @@ @import "../globalCssVariables"; -.search-overview { +.searchItem-overview { display: flex; flex-direction: reverse; justify-content: flex-end; z-index: 0; } -.link-count { - background: black; - border-radius: 20px; - color: white; - width: 15px; - text-align: center; - margin-top: 5px; -} .searchBox-placeholder, -.search-overview .search-item { +.searchItem-overview .searchItem { width: 100%; background: $light-color-secondary; border-color: $intermediate-color; @@ -26,19 +18,19 @@ max-height: 150px; height: auto; z-index: 0; - display: inline-block; - overflow: auto; + display: flex; + overflow: visible; - .main-search-info { + .searchItem-body { display: flex; flex-direction: row; width: 100%; - .search-title-container { + .searchItem-title-container { width: 100%; overflow: hidden; - .search-title { + .searchItem-title { text-transform: uppercase; text-align: left; width: 100%; @@ -46,75 +38,28 @@ } } - .search-info { + .searchItem-info { display: flex; justify-content: flex-end; - .link-container.item { - margin-left: auto; - margin-right: auto; - height: 26px; - width: 26px; - border-radius: 13px; - background: $dark-color; - color: $light-color-secondary; - display: flex; - justify-content: center; - align-items: center; - -webkit-transition: all 0.2s ease-in-out; - -moz-transition: all 0.2s ease-in-out; - -o-transition: all 0.2s ease-in-out; - transition: all 0.2s ease-in-out; - transform-origin: top right; - overflow: hidden; - position: relative; - - - .link-extended { - // display: none; - visibility: hidden; - opacity: 0; - position: relative; - z-index: 500; - overflow: hidden; - -webkit-transition: opacity 0.2s ease-in-out .2s, visibility 0s linear 0s; - -moz-transition: opacity 0.2s ease-in-out .2s, visibility 0s linear 0s; - -o-transition: opacity 0.2s ease-in-out .2s, visibility 0s linear 0s; - transition: opacity 0.2s ease-in-out .2s, visibility 0s linear 0s; - // transition-delay: 1s; - } - - } - - .link-container.item:hover { - width: 70px; - } - - .link-container.item:hover .link-count { - opacity: 0; - } - - .link-container.item:hover .link-extended { - opacity: 1; - visibility: visible; - // display: inline; - } - .icon-icons { width: 50px } .icon-live { width: 175px; + height: 0px; } + .icon-icons { + height:auto; + } .icon-icons, .icon-live { - height: auto; margin: auto; - overflow: hidden; + overflow: visible; - .search-type { + .searchItem-type { display: inline-block; width: 100%; position: absolute; @@ -133,11 +78,11 @@ } } - .search-type:hover+.search-label { + .searchItem-type:hover+.searchItem-label { opacity: 1; } - .search-label { + .searchItem-label { font-size: 10; position: relative; right: 0px; @@ -151,8 +96,6 @@ } .icon-live:hover { - height: 175px; - .pdfBox-cont { img { width: 100% !important; @@ -161,48 +104,51 @@ } } - .search-info:hover { + .searchItem-info:hover { width: 60%; } } } -.search-item:hover~.searchBox-instances, +.searchItem:hover~.searchBox-instances, .searchBox-instances:hover, .searchBox-instances:active { opacity: 1; background: $lighter-alt-accent; - width:150px } -.search-item:hover { +.searchItem:hover { transition: all 0.2s; background: $lighter-alt-accent; } -.search-highlighting { +.searchItem-highlighting { overflow: hidden; text-overflow: ellipsis; white-space: pre; } .searchBox-instances { - float: left; opacity: 1; - width: 0px; + width:40px; + height:40px; + background: gray; transition: all 0.2s ease; color: black; overflow: hidden; + right:-100; + display:inline-block; } -.search-overview:hover { +.searchItem-overview:hover { z-index: 1; } .searchBox-placeholder { min-height: 50px; margin-left: 150px; + width: calc(100% - 150px); text-transform: uppercase; text-align: left; font-weight: bold; diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx index f1d825aa0..32ba5d19d 100644 --- a/src/client/views/search/SearchItem.tsx +++ b/src/client/views/search/SearchItem.tsx @@ -4,24 +4,24 @@ import { faCaretUp, faChartBar, faFile, faFilePdf, faFilm, faFingerprint, faGlob import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { Doc } from "../../../new_fields/Doc"; +import { Doc, DocListCast } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; import { Cast, NumCast, StrCast } from "../../../new_fields/Types"; -import { emptyFunction, returnEmptyString, returnFalse, returnOne, Utils } from "../../../Utils"; +import { emptyFunction, returnEmptyString, returnFalse, returnOne, Utils, emptyPath } from "../../../Utils"; import { DocumentType } from "../../documents/DocumentTypes"; import { DocumentManager } from "../../util/DocumentManager"; import { DragManager, SetupDrag } from "../../util/DragManager"; -import { LinkManager } from "../../util/LinkManager"; import { SearchUtil } from "../../util/SearchUtil"; import { Transform } from "../../util/Transform"; import { SEARCH_THUMBNAIL_SIZE } from "../../views/globalCssVariables.scss"; import { CollectionViewType } from "../collections/CollectionView"; import { CollectionDockingView } from "../collections/CollectionDockingView"; import { ContextMenu } from "../ContextMenu"; -import { DocumentView } from "../nodes/DocumentView"; import { SearchBox } from "./SearchBox"; import "./SearchItem.scss"; import "./SelectorContextMenu.scss"; +import { ContentFittingDocumentView } from "../nodes/ContentFittingDocumentView"; +import { ButtonSelector, ParentDocSelector } from "../collections/ParentDocumentSelector"; export interface SearchItemProps { doc: Doc; @@ -52,7 +52,7 @@ export class SelectorContextMenu extends React.Component<SearchItemProps> { } async fetchDocuments() { - let aliases = (await SearchUtil.GetViewsOfDocument(this.props.doc)).filter(doc => doc !== this.props.doc); + const aliases = (await SearchUtil.GetViewsOfDocument(this.props.doc)).filter(doc => doc !== this.props.doc); const { docs } = await SearchUtil.Search("", true, { fq: `data_l:"${this.props.doc[Id]}"` }); const map: Map<Doc, Doc> = new Map; const allDocs = await Promise.all(aliases.map(doc => SearchUtil.Search("", true, { fq: `data_l:"${doc[Id]}"` }).then(result => result.docs))); @@ -82,7 +82,7 @@ export class SelectorContextMenu extends React.Component<SearchItemProps> { <div className="parents"> <p className="contexts">Contexts:</p> {[...this._docs, ...this._otherDocs].map(doc => { - let item = React.createRef<HTMLDivElement>(); + const item = React.createRef<HTMLDivElement>(); return <div className="collection" key={doc.col[Id] + doc.target[Id]} ref={item}> <div className="collection-item" onPointerDown={ SetupDrag(item, () => doc.col, undefined, undefined, undefined, undefined, () => SearchBox.Instance.closeSearch())}> @@ -135,56 +135,50 @@ export class SearchItem extends React.Component<SearchItemProps> { @observable _displayDim = 50; componentDidMount() { - this.props.doc.search_string = this.props.query; - this.props.doc.search_fields = this.props.highlighting.join(", "); + Doc.SetSearchQuery(this.props.query); + this.props.doc.searchMatch = true; } componentWillUnmount() { - this.props.doc.search_string = undefined; - this.props.doc.search_fields = undefined; + this.props.doc.searchMatch = undefined; } //@computed @action public DocumentIcon() { - let layoutresult = StrCast(this.props.doc.type); + const layoutresult = StrCast(this.props.doc.type); if (!this._useIcons) { - let returnXDimension = () => this._useIcons ? 50 : Number(SEARCH_THUMBNAIL_SIZE); - let returnYDimension = () => this._displayDim; - let scale = () => returnXDimension() / NumCast(Doc.Layout(this.props.doc).nativeWidth, returnXDimension()); + const returnXDimension = () => this._useIcons ? 50 : Number(SEARCH_THUMBNAIL_SIZE); + const returnYDimension = () => this._displayDim; const docview = <div onPointerDown={action(() => { this._useIcons = !this._useIcons; this._displayDim = this._useIcons ? 50 : Number(SEARCH_THUMBNAIL_SIZE); })} - onPointerEnter={action(() => this._displayDim = this._useIcons ? 50 : Number(SEARCH_THUMBNAIL_SIZE))} - onPointerLeave={action(() => this._displayDim = 50)} > - <DocumentView - fitToBox={StrCast(this.props.doc.type).indexOf(DocumentType.COL) !== -1} + onPointerEnter={action(() => this._displayDim = this._useIcons ? 50 : Number(SEARCH_THUMBNAIL_SIZE))} > + <ContentFittingDocumentView Document={this.props.doc} + LibraryPath={emptyPath} + fitToBox={StrCast(this.props.doc.type).indexOf(DocumentType.COL) !== -1} addDocument={returnFalse} removeDocument={returnFalse} ruleProvider={undefined} - ScreenToLocalTransform={Transform.Identity} addDocTab={returnFalse} pinToPres={returnFalse} + getTransform={Transform.Identity} renderDepth={1} PanelWidth={returnXDimension} PanelHeight={returnYDimension} focus={emptyFunction} - backgroundColor={returnEmptyString} - parentActive={returnFalse} + moveDocument={returnFalse} + active={returnFalse} whenActiveChanged={returnFalse} - bringToFront={emptyFunction} - zoomToScale={emptyFunction} - getScale={returnOne} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} - ContentScaling={scale} + setPreviewScript={emptyFunction} + previewScript={undefined} /> </div>; return docview; } - let button = layoutresult.indexOf(DocumentType.PDF) !== -1 ? faFilePdf : + const button = layoutresult.indexOf(DocumentType.PDF) !== -1 ? faFilePdf : layoutresult.indexOf(DocumentType.IMG) !== -1 ? faImage : layoutresult.indexOf(DocumentType.TEXT) !== -1 ? faStickyNote : layoutresult.indexOf(DocumentType.VID) !== -1 ? faFilm : @@ -194,40 +188,28 @@ export class SearchItem extends React.Component<SearchItemProps> { layoutresult.indexOf(DocumentType.HIST) !== -1 ? faChartBar : layoutresult.indexOf(DocumentType.WEB) !== -1 ? faGlobeAsia : faCaretUp; - return <div onPointerDown={action(() => { this._useIcons = false; this._displayDim = Number(SEARCH_THUMBNAIL_SIZE); })} > + return <div onClick={action(() => { this._useIcons = false; this._displayDim = Number(SEARCH_THUMBNAIL_SIZE); })} > <FontAwesomeIcon icon={button} size="2x" /> </div>; } collectionRef = React.createRef<HTMLDivElement>(); - startDocDrag = () => { - let doc = this.props.doc; - const isProto = Doc.GetT(doc, "isPrototype", "boolean", true); - if (isProto) { - return Doc.MakeDelegate(doc); - } else { - return Doc.MakeAlias(doc); - } - } - - @computed - get linkCount() { return LinkManager.Instance.getAllRelatedLinks(this.props.doc).length; } @action pointerDown = (e: React.PointerEvent) => { e.preventDefault(); e.button === 0 && SearchBox.Instance.openSearch(e); } nextHighlight = (e: React.PointerEvent) => { - e.preventDefault(); e.button === 0 && SearchBox.Instance.openSearch(e); - let sstring = StrCast(this.props.doc.search_string); - this.props.doc.search_string = ""; - setTimeout(() => this.props.doc.search_string = sstring, 0); + e.preventDefault(); + e.button === 0 && SearchBox.Instance.openSearch(e); + this.props.doc.searchMatch = false; + setTimeout(() => this.props.doc.searchMatch = true, 0); } highlightDoc = (e: React.PointerEvent) => { if (this.props.doc.type === DocumentType.LINK) { if (this.props.doc.anchor1 && this.props.doc.anchor2) { - let doc1 = Cast(this.props.doc.anchor1, Doc, null); - let doc2 = Cast(this.props.doc.anchor2, Doc, null); + const doc1 = Cast(this.props.doc.anchor1, Doc, null); + const doc2 = Cast(this.props.doc.anchor2, Doc, null); Doc.BrushDoc(doc1); Doc.BrushDoc(doc2); } @@ -241,8 +223,8 @@ export class SearchItem extends React.Component<SearchItemProps> { if (this.props.doc.type === DocumentType.LINK) { if (this.props.doc.anchor1 && this.props.doc.anchor2) { - let doc1 = Cast(this.props.doc.anchor1, Doc, null); - let doc2 = Cast(this.props.doc.anchor2, Doc, null); + const doc1 = Cast(this.props.doc.anchor1, Doc, null); + const doc2 = Cast(this.props.doc.anchor2, Doc, null); Doc.UnBrushDoc(doc1); Doc.UnBrushDoc(doc2); } @@ -264,46 +246,62 @@ export class SearchItem extends React.Component<SearchItemProps> { ContextMenu.Instance.displayMenu(e.clientX, e.clientY); } + _downX = 0; + _downY = 0; + _target: any; onPointerDown = (e: React.PointerEvent<HTMLDivElement>) => { + this._downX = e.clientX; + this._downY = e.clientY; e.stopPropagation(); - const doc = Doc.IsPrototype(this.props.doc) ? Doc.MakeDelegate(this.props.doc) : this.props.doc; - DragManager.StartDocumentDrag([e.currentTarget], new DragManager.DocumentDragData([doc]), e.clientX, e.clientY, { - handlers: { dragComplete: emptyFunction }, - hideSource: false, - }); + this._target = e.currentTarget; + document.removeEventListener("pointermove", this.onPointerMoved); + document.removeEventListener("pointerup", this.onPointerUp); + document.addEventListener("pointermove", this.onPointerMoved); + document.addEventListener("pointerup", this.onPointerUp); + } + onPointerMoved = (e: PointerEvent) => { + if (Math.abs(e.clientX - this._downX) > Utils.DRAG_THRESHOLD || + Math.abs(e.clientY - this._downY) > Utils.DRAG_THRESHOLD) { + console.log("DRAGGIGNG"); + document.removeEventListener("pointermove", this.onPointerMoved); + document.removeEventListener("pointerup", this.onPointerUp); + const doc = Doc.IsPrototype(this.props.doc) ? Doc.MakeDelegate(this.props.doc) : this.props.doc; + DragManager.StartDocumentDrag([this._target], new DragManager.DocumentDragData([doc]), e.clientX, e.clientY); + } + } + onPointerUp = (e: PointerEvent) => { + document.removeEventListener("pointermove", this.onPointerMoved); + document.removeEventListener("pointerup", this.onPointerUp); + } + + @computed + get contextButton() { + return <ParentDocSelector Views={DocumentManager.Instance.DocumentViews} Document={this.props.doc} addDocTab={(doc, data, where) => CollectionDockingView.AddRightSplit(doc, data)} />; } render() { const doc1 = Cast(this.props.doc.anchor1, Doc); const doc2 = Cast(this.props.doc.anchor2, Doc); - return ( - <div className="search-overview" onPointerDown={this.pointerDown} onContextMenu={this.onContextMenu}> - <div className="search-item" onPointerDown={this.nextHighlight} onPointerEnter={this.highlightDoc} onPointerLeave={this.unHighlightDoc} id="result" - onClick={this.onClick}> - <div className="main-search-info"> - <div title="Drag as document" onPointerDown={this.onPointerDown} style={{ marginRight: "7px" }}> <FontAwesomeIcon icon="file" size="lg" /> - <div className="link-container item"> - <div className="link-count" title={`${this.linkCount + " links"}`}>{this.linkCount}</div> - </div> - </div> - <div className="search-title-container"> - <div className="search-title">{StrCast(this.props.doc.title)}</div> - <div className="search-highlighting">{this.props.highlighting.length ? "Matched fields:" + this.props.highlighting.join(", ") : this.props.lines.length ? this.props.lines[0] : ""}</div> - {this.props.lines.filter((m, i) => i).map((l, i) => <div id={i.toString()} className="search-highlighting">`${l}`</div>)} - </div> - <div className="search-info" style={{ width: this._useIcons ? "15%" : "400px" }}> - <div className={`icon-${this._useIcons ? "icons" : "live"}`}> - <div className="search-type" title="Click to Preview">{this.DocumentIcon()}</div> - <div className="search-label">{this.props.doc.type ? this.props.doc.type : "Other"}</div> - </div> - </div> + return <div className="searchItem-overview" onPointerDown={this.pointerDown} onContextMenu={this.onContextMenu}> + <div className="searchItem" onPointerDown={this.nextHighlight} onPointerEnter={this.highlightDoc} onPointerLeave={this.unHighlightDoc}> + <div className="searchItem-body" onClick={this.onClick}> + <div className="searchItem-title-container"> + <div className="searchItem-title">{StrCast(this.props.doc.title)}</div> + <div className="searchItem-highlighting">{this.props.highlighting.length ? "Matched fields:" + this.props.highlighting.join(", ") : this.props.lines.length ? this.props.lines[0] : ""}</div> + {this.props.lines.filter((m, i) => i).map((l, i) => <div id={i.toString()} className="searchItem-highlighting">`${l}`</div>)} + </div> + </div> + <div className="searchItem-info" style={{ width: this._useIcons ? "30px" : "100%" }}> + <div className={`icon-${this._useIcons ? "icons" : "live"}`}> + <div className="searchItem-type" title="Click to Preview" onPointerDown={this.onPointerDown}>{this.DocumentIcon()}</div> + <div className="searchItem-label">{this.props.doc.type ? this.props.doc.type : "Other"}</div> </div> </div> - <div className="searchBox-instances"> + <div className="searchItem-context" title="Drag as document"> {(doc1 instanceof Doc && doc2 instanceof Doc) && this.props.doc.type === DocumentType.LINK ? <LinkContextMenu doc1={doc1} doc2={doc2} /> : - <SelectorContextMenu {...this.props} />} + this.contextButton} </div> </div> - ); + </div>; } }
\ No newline at end of file diff --git a/src/client/views/search/ToggleBar.tsx b/src/client/views/search/ToggleBar.tsx index ed5ecd3ba..e4d7f2fd5 100644 --- a/src/client/views/search/ToggleBar.tsx +++ b/src/client/views/search/ToggleBar.tsx @@ -33,8 +33,7 @@ export class ToggleBar extends React.Component<ToggleBarProps>{ } componentDidMount = () => { - - let totalWidth = 265; + const totalWidth = 265; if (this._originalStatus) { this._forwardTimeline.add({ |
