diff options
Diffstat (limited to 'src/client/views/search')
| -rw-r--r-- | src/client/views/search/FilterBox.tsx | 13 | ||||
| -rw-r--r-- | src/client/views/search/Pager.tsx | 8 | ||||
| -rw-r--r-- | src/client/views/search/SearchBox.tsx | 3 | ||||
| -rw-r--r-- | src/client/views/search/SearchItem.scss | 58 | ||||
| -rw-r--r-- | src/client/views/search/SearchItem.tsx | 154 | ||||
| -rw-r--r-- | src/client/views/search/ToggleBar.tsx | 2 |
6 files changed, 176 insertions, 62 deletions
diff --git a/src/client/views/search/FilterBox.tsx b/src/client/views/search/FilterBox.tsx index 8faf0a991..5d36e650b 100644 --- a/src/client/views/search/FilterBox.tsx +++ b/src/client/views/search/FilterBox.tsx @@ -64,7 +64,7 @@ export class FilterBox extends React.Component { componentDidMount = () => { document.addEventListener("pointerdown", (e) => { - if (e.timeStamp !== this._pointerTime) { + if (!e.defaultPrevented && e.timeStamp !== this._pointerTime) { SearchBox.Instance.closeSearch(); } }); @@ -72,9 +72,9 @@ export class FilterBox extends React.Component { setupAccordion() { $('document').ready(function () { - var acc = document.getElementsByClassName('filter-header'); - - for (var i = 0; i < acc.length; i++) { + const acc = document.getElementsByClassName('filter-header'); + // tslint:disable-next-line: prefer-for-of + for (let i = 0; i < acc.length; i++) { acc[i].addEventListener("click", function (this: HTMLElement) { this.classList.toggle("active"); @@ -103,6 +103,7 @@ export class FilterBox extends React.Component { $('document').ready(function () { var 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; if (classList.contains("active")) { @@ -247,8 +248,8 @@ export class FilterBox extends React.Component { filterDocsByType(docs: Doc[]) { let finalDocs: Doc[] = []; docs.forEach(doc => { - let layoutresult = Cast(doc.type, "string", ""); - if (this._icons.includes(layoutresult)) { + let layoutresult = Cast(doc.type, "string"); + if (!layoutresult || this._icons.includes(layoutresult)) { finalDocs.push(doc); } }); diff --git a/src/client/views/search/Pager.tsx b/src/client/views/search/Pager.tsx index e7d3b810f..9bcfb1676 100644 --- a/src/client/views/search/Pager.tsx +++ b/src/client/views/search/Pager.tsx @@ -3,7 +3,7 @@ import { observer } from 'mobx-react'; import { faArrowCircleRight, faArrowCircleLeft } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { library } from '@fortawesome/fontawesome-svg-core'; -import "./Pager.scss" +import "./Pager.scss"; import { SearchBox } from './SearchBox'; import { observable, action } from 'mobx'; import { FilterBox } from './FilterBox'; @@ -20,7 +20,7 @@ export class Pager extends React.Component { @action onLeftClick(e: React.PointerEvent) { FilterBox.Instance._pointerTime = e.timeStamp; - if(SearchBox.Instance._pageNum > 0){ + if (SearchBox.Instance._pageNum > 0) { SearchBox.Instance._pageNum -= 1; } } @@ -28,7 +28,7 @@ export class Pager extends React.Component { @action onRightClick(e: React.PointerEvent) { FilterBox.Instance._pointerTime = e.timeStamp; - if(SearchBox.Instance._pageNum+1 < SearchBox.Instance._maxNum){ + if (SearchBox.Instance._pageNum + 1 < SearchBox.Instance._maxNum) { SearchBox.Instance._pageNum += 1; } } @@ -72,7 +72,7 @@ export class Pager extends React.Component { </div> </div> </div> - ) + ); } }
\ No newline at end of file diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index dbaa6eba2..af0c541f1 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -15,7 +15,6 @@ import { Id } from '../../../new_fields/FieldSymbols'; import { SearchUtil } from '../../util/SearchUtil'; import { RouteStore } from '../../../server/RouteStore'; import { FilterBox } from './FilterBox'; -import { Pager } from './Pager'; @observer export class SearchBox extends React.Component { @@ -169,7 +168,7 @@ export class SearchBox extends React.Component { @action.bound closeSearch = () => { - console.log("closing search") + console.log("closing search"); FilterBox.Instance.closeFilter(); this.closeResults(); } diff --git a/src/client/views/search/SearchItem.scss b/src/client/views/search/SearchItem.scss index 946680f0e..fa4c9cb38 100644 --- a/src/client/views/search/SearchItem.scss +++ b/src/client/views/search/SearchItem.scss @@ -5,6 +5,7 @@ flex-direction: row-reverse; justify-content: flex-end; height: 70px; + z-index: 0; .search-item { width: 500px; @@ -13,6 +14,7 @@ border-bottom-style: solid; padding: 10px; height: 70px; + z-index: 0; display: inline-block; .main-search-info { @@ -23,16 +25,17 @@ .search-title { text-transform: uppercase; text-align: left; - width: 80%; + width: 100%; font-weight: bold; } .search-info { display: flex; justify-content: flex-end; - width: 40%; .link-container.item { + margin-left: auto; + margin-right: auto; height: 26px; width: 26px; border-radius: 13px; @@ -41,7 +44,6 @@ display: flex; justify-content: center; align-items: center; - right: 15px; -webkit-transition: all 0.2s ease-in-out; -moz-transition: all 0.2s ease-in-out; -o-transition: all 0.2s ease-in-out; @@ -84,26 +86,42 @@ .link-container.item:hover .link-extended { opacity: 1; } + + .icon-icons { + width:50px + } + .icon-live { + width:175px; + } - .icon { - + .icon-icons, .icon-live { + height:50px; + margin:auto; + overflow: hidden; .search-type { - width: 25PX; - height: 25PX; - display: flex; + display: inline-block; + width:100%; + position: absolute; justify-content: center; align-items: center; position: relative; margin-right: 5px; } + .pdfBox-cont { + overflow: hidden; + + img { + width:100% !important; + height:auto !important; + } + } .search-type:hover+.search-label { opacity: 1; } .search-label { font-size: 10; - padding: 5px; position: relative; right: 0px; text-transform: capitalize; @@ -114,6 +132,18 @@ transition: opacity 0.2s ease-in-out; } } + + .icon-live:hover { + height:175px; + .pdfBox-cont { + img { + width:100% !important; + } + } + } + } + .search-info:hover { + width:60%; } } } @@ -143,7 +173,15 @@ -webkit-transform: scale(0); -ms-transform: scale(0); transform: scale(0); - // height: 100% } +} +.search-overview:hover { + z-index: 1; +} +.collection { + display:flex; +} +.collection-item { + width:35px; }
\ No newline at end of file diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx index 50bf1f6b8..f8a0c7b16 100644 --- a/src/client/views/search/SearchItem.tsx +++ b/src/client/views/search/SearchItem.tsx @@ -1,24 +1,26 @@ import React = require("react"); import { library } from '@fortawesome/fontawesome-svg-core'; -import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote, faMusic, faLink, faChartBar, faGlobeAsia } from '@fortawesome/free-solid-svg-icons'; +import { faCaretUp, faChartBar, faFilePdf, faFilm, faGlobeAsia, faImage, faLink, faMusic, faObjectGroup, faStickyNote } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Cast, NumCast } from "../../../new_fields/Types"; -import { observable, runInAction, computed, action } from "mobx"; -import { listSpec } from "../../../new_fields/Schema"; -import { Doc } from "../../../new_fields/Doc"; +import { action, computed, observable, runInAction } from "mobx"; +import { observer } from "mobx-react"; +import { Doc, DocListCast, HeightSym, WidthSym } from "../../../new_fields/Doc"; +import { Id } from "../../../new_fields/FieldSymbols"; +import { Cast, NumCast, StrCast } from "../../../new_fields/Types"; +import { emptyFunction, returnFalse, returnOne } from "../../../Utils"; +import { DocTypes } from "../../documents/Documents"; import { DocumentManager } from "../../util/DocumentManager"; import { SetupDrag } from "../../util/DragManager"; +import { LinkManager } from "../../util/LinkManager"; import { SearchUtil } from "../../util/SearchUtil"; -import { Id } from "../../../new_fields/FieldSymbols"; -import { CollectionDockingView } from "../collections/CollectionDockingView"; -import { observer } from "mobx-react"; -import "./SearchItem.scss"; +import { Transform } from "../../util/Transform"; +import { SEARCH_THUMBNAIL_SIZE } from "../../views/globalCssVariables.scss"; import { CollectionViewType } from "../collections/CollectionBaseView"; -import { DocTypes } from "../../documents/Documents"; -import { FilterBox } from "./FilterBox"; +import { CollectionDockingView } from "../collections/CollectionDockingView"; import { DocumentView } from "../nodes/DocumentView"; -import "./SelectorContextMenu.scss"; import { SearchBox } from "./SearchBox"; +import "./SearchItem.scss"; +import "./SelectorContextMenu.scss"; export interface SearchItemProps { doc: Doc; @@ -66,16 +68,23 @@ export class SelectorContextMenu extends React.Component<SearchItemProps> { col.panX = newPanX; col.panY = newPanY; } - CollectionDockingView.Instance.AddRightSplit(col); + CollectionDockingView.Instance.AddRightSplit(col, undefined); }; } - render() { return ( - < div className="parents"> + <div className="parents"> <p className="contexts">Contexts:</p> - {this._docs.map(doc => <div className="collection"><a className="title" onClick={this.getOnClick(doc)}>{doc.col.title}</a></div>)} - {this._otherDocs.map(doc => <div className="collection"><a className="title" onClick={this.getOnClick(doc)}>{doc.col.title}</a></div>)} + {[...this._docs, ...this._otherDocs].map(doc => { + let 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())}> + <FontAwesomeIcon icon={faStickyNote} /> + </div> + <a className="title" onClick={this.getOnClick(doc)}>{doc.col.title}</a> + </div>; + })} </div> ); } @@ -87,12 +96,58 @@ export class SearchItem extends React.Component<SearchItemProps> { @observable _selected: boolean = false; onClick = () => { - CollectionDockingView.Instance.AddRightSplit(this.props.doc); + DocumentManager.Instance.jumpToDocument(this.props.doc, false); } + @observable _useIcons = true; + @observable _displayDim = 50; @computed public get DocumentIcon() { - let layoutresult = Cast(this.props.doc.type, "string", ""); + let layoutresult = StrCast(this.props.doc.type); + if (!this._useIcons) { + let renderDoc = this.props.doc; + let box: number[] = []; + if (layoutresult.indexOf(DocTypes.COL) !== -1) { + renderDoc = Doc.MakeDelegate(renderDoc); + let bounds = DocListCast(renderDoc.data).reduce((bounds, doc) => { + var [sptX, sptY] = [NumCast(doc.x), NumCast(doc.y)]; + let [bptX, bptY] = [sptX + doc[WidthSym](), sptY + doc[HeightSym]()]; + return { + x: Math.min(sptX, bounds.x), y: Math.min(sptY, bounds.y), + r: Math.max(bptX, bounds.r), b: Math.max(bptY, bounds.b) + }; + }, { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: Number.MIN_VALUE, b: Number.MIN_VALUE }); + box = [(bounds.x + bounds.r) / 2, (bounds.y + bounds.b) / 2, Number(SEARCH_THUMBNAIL_SIZE) / (bounds.r - bounds.x), this._displayDim]; + } + let returnXDimension = () => this._useIcons ? 50 : Number(SEARCH_THUMBNAIL_SIZE); + let returnYDimension = () => this._displayDim; + let scale = () => returnXDimension() / NumCast(renderDoc.nativeWidth, returnXDimension()); + return <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={box} + Document={renderDoc} + addDocument={returnFalse} + removeDocument={returnFalse} + ScreenToLocalTransform={Transform.Identity} + addDocTab={returnFalse} + renderDepth={1} + PanelWidth={returnXDimension} + PanelHeight={returnYDimension} + focus={emptyFunction} + selectOnLoad={false} + parentActive={returnFalse} + whenActiveChanged={returnFalse} + bringToFront={emptyFunction} + zoomToScale={emptyFunction} + getScale={returnOne} + ContainingCollectionView={undefined} + ContentScaling={scale} + /> + </div>; + } let button = layoutresult.indexOf(DocTypes.PDF) !== -1 ? faFilePdf : layoutresult.indexOf(DocTypes.IMG) !== -1 ? faImage : @@ -104,7 +159,9 @@ export class SearchItem extends React.Component<SearchItemProps> { layoutresult.indexOf(DocTypes.HIST) !== -1 ? faChartBar : layoutresult.indexOf(DocTypes.WEB) !== -1 ? faGlobeAsia : faCaretUp; - return <FontAwesomeIcon icon={button} size="2x" />; + return <div onPointerDown={action(() => { this._useIcons = false; this._displayDim = Number(SEARCH_THUMBNAIL_SIZE); })} > + <FontAwesomeIcon icon={button} size="2x" /> + </div>; } collectionRef = React.createRef<HTMLDivElement>(); @@ -119,7 +176,7 @@ export class SearchItem extends React.Component<SearchItemProps> { } @computed - get linkCount() { return Cast(this.props.doc.linkedToDocs, listSpec(Doc), []).length + Cast(this.props.doc.linkedFromDocs, listSpec(Doc), []).length; } + get linkCount() { return LinkManager.Instance.getAllRelatedLinks(this.props.doc).length; } @computed get linkString(): string { @@ -130,40 +187,59 @@ export class SearchItem extends React.Component<SearchItemProps> { return num.toString() + " links"; } - pointerDown = (e: React.PointerEvent) => { SearchBox.Instance.openSearch(e); }; + @action + pointerDown = (e: React.PointerEvent) => SearchBox.Instance.openSearch(e) highlightDoc = (e: React.PointerEvent) => { - let docViews: DocumentView[] = DocumentManager.Instance.getAllDocumentViews(this.props.doc); - docViews.forEach(element => { - element.props.Document.libraryBrush = true; - }); + if (this.props.doc.type === DocTypes.LINK) { + if (this.props.doc.anchor1 && this.props.doc.anchor2) { + + let doc1 = Cast(this.props.doc.anchor1, Doc, new Doc()); + let doc2 = Cast(this.props.doc.anchor2, Doc, new Doc()); + doc1.libraryBrush = true; + doc2.libraryBrush = true; + } + } else { + let docViews: DocumentView[] = DocumentManager.Instance.getAllDocumentViews(this.props.doc); + docViews.forEach(element => { + element.props.Document.libraryBrush = true; + }); + } } unHighlightDoc = (e: React.PointerEvent) => { - let docViews: DocumentView[] = DocumentManager.Instance.getAllDocumentViews(this.props.doc); - docViews.forEach(element => { - element.props.Document.libraryBrush = false; - }); + if (this.props.doc.type === DocTypes.LINK) { + if (this.props.doc.anchor1 && this.props.doc.anchor2) { + + let doc1 = Cast(this.props.doc.anchor1, Doc, new Doc()); + let doc2 = Cast(this.props.doc.anchor2, Doc, new Doc()); + doc1.libraryBrush = false; + doc2.libraryBrush = false; + } + } else { + let docViews: DocumentView[] = DocumentManager.Instance.getAllDocumentViews(this.props.doc); + docViews.forEach(element => { + element.props.Document.libraryBrush = false; + }); + } } render() { return ( <div className="search-overview" onPointerDown={this.pointerDown}> - <div className="search-item" onPointerEnter={this.highlightDoc} onPointerLeave={this.unHighlightDoc} ref={this.collectionRef} id="result" onClick={this.onClick} onPointerDown={() => { - this.pointerDown; - SetupDrag(this.collectionRef, this.startDocDrag); - }} > + <div className="search-item" onPointerEnter={this.highlightDoc} onPointerLeave={this.unHighlightDoc} ref={this.collectionRef} id="result" + onClick={this.onClick} onPointerDown={this.pointerDown} > <div className="main-search-info"> <div className="search-title" id="result" >{this.props.doc.title}</div> - <div className="search-info"> + <div className="search-info" style={{ width: this._useIcons ? "15%" : "400px" }}> + <div className={`icon-${this._useIcons ? "icons" : "live"}`}> + <div className="search-type" >{this.DocumentIcon}</div> + <div className="search-label">{this.props.doc.type}</div> + </div> <div className="link-container item"> <div className="link-count">{this.linkCount}</div> <div className="link-extended">{this.linkString}</div> </div> - <div className="icon"> - <div className="search-type" >{this.DocumentIcon}</div> - <div className="search-label">{this.props.doc.type}</div> - </div> </div> </div> </div> diff --git a/src/client/views/search/ToggleBar.tsx b/src/client/views/search/ToggleBar.tsx index 8a3aacf96..178578c5c 100644 --- a/src/client/views/search/ToggleBar.tsx +++ b/src/client/views/search/ToggleBar.tsx @@ -78,7 +78,7 @@ export class ToggleBar extends React.Component<ToggleBarProps>{ <div className="toggle-option" style={{ opacity: (this.props.getStatus() ? .4 : 1) }}>{this.props.optionTwo}</div> </div> <div className="toggle-bar" id="toggle-bar" onClick={this.onclick} style={{ flexDirection: (this._originalStatus ? "row" : "row-reverse") }}> - <div className="toggle-button" id="toggle-button" ref={this._toggleButton} /> + <div className="toggle-button" id="toggle-button" ref={this._toggleButton} /> </div> </div> ); |
