aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/search
diff options
context:
space:
mode:
authorab <abdullah_ahmed@brown.edu>2019-07-01 15:40:55 -0400
committerab <abdullah_ahmed@brown.edu>2019-07-01 15:40:55 -0400
commit0fc7edd5f9bd1234f8de6e5b1c7b8f23668d784c (patch)
tree2ddff97c032657fb86de37c3be2cf2d201980088 /src/client/views/search
parent4f8b7cecea3ceed6861c38bde9ce03c9c46e2d09 (diff)
parent6bd79baf2d9301304194d87667bb5c66c17e5298 (diff)
Merge branch 'monikasearch2' of https://github.com/browngraphicslab/Dash-Web into text_box_ab
Diffstat (limited to 'src/client/views/search')
-rw-r--r--src/client/views/search/FilterBox.scss56
-rw-r--r--src/client/views/search/FilterBox.tsx89
-rw-r--r--src/client/views/search/Pager.tsx12
-rw-r--r--src/client/views/search/SearchBox.scss7
-rw-r--r--src/client/views/search/SearchBox.tsx8
-rw-r--r--src/client/views/search/SearchItem.scss58
-rw-r--r--src/client/views/search/SearchItem.tsx191
-rw-r--r--src/client/views/search/SelectorContextMenu.scss1
-rw-r--r--src/client/views/search/ToggleBar.tsx1
9 files changed, 351 insertions, 72 deletions
diff --git a/src/client/views/search/FilterBox.scss b/src/client/views/search/FilterBox.scss
index 1eb8963d7..1b73916c9 100644
--- a/src/client/views/search/FilterBox.scss
+++ b/src/client/views/search/FilterBox.scss
@@ -105,4 +105,60 @@
border-top-style: solid;
padding-top: 10px;
}
+}
+
+.active-filters {
+ display: flex;
+ flex-direction: row-reverse;
+ justify-content: flex-end;
+ width: 100%;
+ margin-right: 30px;
+ position: relative;
+
+ .active-icon {
+ max-width: 40px;
+ flex: initial;
+
+ &.icon{
+ width: 40px;
+ text-align: center;
+ margin-bottom: 5px;
+ position: absolute;
+ }
+
+ &.container {
+ display: flex;
+ flex-direction: column;
+ width: 40px;
+ }
+
+ &.description {
+ text-align: center;
+ top: 40px;
+ position: absolute;
+ width: 40px;
+ font-size: 9px;
+ opacity: 0;
+ -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;
+ }
+
+ &.icon:hover + .description {
+ opacity: 1;
+ }
+ }
+
+ .col-icon {
+ height: 35px;
+ margin-left: 5px;
+ width: 35px;
+ background-color: black;
+ color: white;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
} \ No newline at end of file
diff --git a/src/client/views/search/FilterBox.tsx b/src/client/views/search/FilterBox.tsx
index cc1feeaf7..6053db595 100644
--- a/src/client/views/search/FilterBox.tsx
+++ b/src/client/views/search/FilterBox.tsx
@@ -2,8 +2,8 @@ import * as React from 'react';
import { observer } from 'mobx-react';
import { observable, action } from 'mobx';
import "./SearchBox.scss";
-import { faTimes } from '@fortawesome/free-solid-svg-icons';
-import { library} from '@fortawesome/fontawesome-svg-core';
+import { faTimes, faCheckCircle, faObjectGroup } from '@fortawesome/free-solid-svg-icons';
+import { library } from '@fortawesome/fontawesome-svg-core';
import { Doc } from '../../../new_fields/Doc';
import { Id } from '../../../new_fields/FieldSymbols';
import { DocTypes } from '../../documents/Documents';
@@ -19,8 +19,11 @@ import { NaviconButton } from './NaviconButton';
import * as $ from 'jquery';
import "./FilterBox.scss";
import { SearchBox } from './SearchBox';
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
library.add(faTimes);
+library.add(faCheckCircle);
+library.add(faObjectGroup);
export enum Keys {
TITLE = "title",
@@ -35,12 +38,16 @@ export class FilterBox extends React.Component {
public _allIcons: string[] = [DocTypes.AUDIO, DocTypes.COL, DocTypes.HIST, DocTypes.IMG, DocTypes.LINK, DocTypes.PDF, DocTypes.TEXT, DocTypes.VID, DocTypes.WEB];
//if true, any keywords can be used. if false, all keywords are required.
+ //this also serves as an indicator if the word status filter is applied
@observable private _basicWordStatus: boolean = true;
@observable private _filterOpen: boolean = false;
+ //if icons = all icons, then no icon filter is applied
@observable private _icons: string[] = this._allIcons;
+ //if all of these are true, no key filter is applied
@observable private _titleFieldStatus: boolean = true;
@observable private _authorFieldStatus: boolean = true;
@observable private _dataFieldStatus: boolean = true;
+ //this also serves as an indicator if the collection status filter is applied
@observable private _collectionStatus = false;
@observable private _collectionSelfStatus = true;
@observable private _collectionParentStatus = true;
@@ -57,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();
}
});
@@ -65,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");
@@ -96,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")) {
@@ -240,14 +248,48 @@ 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);
}
});
return finalDocs;
}
+ getABCicon() {
+ return (
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 87.8 87.8" height="35">
+ <path d="M25.4 47.9c-1.3 1.3-1.9 2.8-1.9 4.8 0 3.8 2.3 6.1 6.1 6.1 5.1 0 8-3.3 9-6.2 0.2-0.7 0.4-1.4 0.4-2.1v-6.1c-0.1 0-0.1 0-0.2 0C32.2 44.5 27.7 45.6 25.4 47.9z" />
+ <path d="M64.5 28.6c-2.2 0-4.1 1.5-4.7 3.8l0 0.2c-0.1 0.3-0.1 0.7-0.1 1.1v3.3c0 0.4 0.1 0.8 0.2 1.1 0.6 2.2 2.4 3.6 4.6 3.6 3.2 0 5.2-2.6 5.2-6.7C69.5 31.8 68 28.6 64.5 28.6z" />
+ <path d="M43.9 0C19.7 0 0 19.7 0 43.9s19.7 43.9 43.9 43.9 43.9-19.6 43.9-43.9S68.1 0 43.9 0zM40.1 65.5l-0.5-4c-3 3.1-7.4 4.9-12.1 4.9 -6.8 0-13.6-4.4-13.6-12.8 0-4 1.3-7.4 4-10 4.1-4.1 11.1-6.2 20.8-6.3 0-5.5-2.9-8.4-8.3-8.4 -3.6 0-7.4 1.1-10.2 2.9l-1.1 0.7 -2.4-6.9 0.7-0.4c3.7-2.4 8.9-3.8 14.1-3.8 10.9 0 16.7 6.2 16.7 17.9V54.6c0 4.1 0.2 7.2 0.7 9.7L49 65.5H40.1zM65.5 67.5c1.8 0 3-0.5 4-0.9l0.5-0.2 0.8 3.4 -0.3 0.2c-1 0.5-3 1.1-5.5 1.1 -5.8 0-9.7-4-9.7-9.9 0-6.1 4.3-10.3 10.4-10.3 2.1 0 4 0.5 4.9 1l0.3 0.2 -1 3.5 -0.5-0.3c-0.7-0.4-1.8-0.8-3.7-0.8 -3.7 0-6.1 2.6-6.1 6.6C59.5 64.8 61.9 67.5 65.5 67.5zM65 45.3c-2.5 0-4.5-0.9-5.9-2.7l-0.1 2.3h-3.8l0-0.5c0.1-1.2 0.2-3.1 0.2-4.8V16.7h4.3v10.8c1.4-1.6 3.5-2.5 6-2.5 2.2 0 4.1 0.8 5.5 2.3 1.8 1.8 2.8 4.5 2.8 7.7C73.8 42.1 69.3 45.3 65 45.3z" />
+ </svg>
+ );
+ }
+
+ getTypeIcon() {
+ return (
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 87.8 87.8" height="35">
+ <path d="M43.9 0C19.7 0 0 19.7 0 43.9s19.7 43.9 43.9 43.9 43.9-19.6 43.9-43.9S68.1 0 43.9 0zM43.9 12.2c4.1 0 7.5 3.4 7.5 7.5 0 4.1-3.4 7.5-7.5 7.5 -4.1 0-7.5-3.4-7.5-7.5C36.4 15.5 39.7 12.2 43.9 12.2zM11.9 50.4l7.5-13 7.5 13H11.9zM47.6 75.7h-7.5l-3.7-6.5 3.8-6.5h7.5l3.8 6.5L47.6 75.7zM70.7 70.7c-0.2 0.2-0.4 0.3-0.7 0.3s-0.5-0.1-0.7-0.3l-25.4-25.4 -25.4 25.4c-0.2 0.2-0.4 0.3-0.7 0.3s-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1 0-1.4l25.4-25.4 -25.4-25.4c-0.4-0.4-0.4-1 0-1.4s1-0.4 1.4 0l25.4 25.4 25.4-25.4c0.4-0.4 1-0.4 1.4 0s0.4 1 0 1.4l-25.4 25.4 25.4 25.4C71.1 69.7 71.1 70.3 70.7 70.7zM61.4 51.4v-15h15v15H61.4z" />
+ </svg>
+ );
+ }
+
+ getKeyIcon() {
+ return (
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 87.8 87.8" height="35">
+ <path d="M38.5 32.4c0 3.4-2.7 6.1-6.1 6.1 -3.4 0-6.1-2.7-6.1-6.1 0-3.4 2.8-6.1 6.1-6.1C35.8 26.3 38.5 29 38.5 32.4zM87.8 43.9c0 24.2-19.6 43.9-43.9 43.9S0 68.1 0 43.9C0 19.7 19.7 0 43.9 0S87.8 19.7 87.8 43.9zM66.8 60.3L50.2 43.7c-0.5-0.5-0.6-1.2-0.4-1.8 2.4-5.6 1.1-12.1-3.2-16.5 -5.9-5.8-15.4-5.8-21.2 0l0 0c-4.3 4.3-5.6 10.8-3.2 16.5 3.2 7.6 12 11.2 19.7 8 0.6-0.3 1.4-0.1 1.8 0.4l3.1 3.1h3.9c1.2 0 2.2 1 2.2 2.2v3.6h3.6c1.2 0 2.2 1 2.2 2.2v4l1.6 1.6h6.5V60.3z" />
+ </svg>
+ );
+ }
+
+ getColIcon() {
+ return (
+ <div className="col-icon">
+ <FontAwesomeIcon icon={faObjectGroup} size="lg" />
+ </div>
+ );
+ }
+
@action.bound
openFilter = () => {
this._filterOpen = !this._filterOpen;
@@ -259,7 +301,7 @@ export class FilterBox extends React.Component {
@action.bound
handleWordQueryChange = () => { this._basicWordStatus = !this._basicWordStatus; }
- @action
+ @action.bound
getBasicWordStatus() { return this._basicWordStatus; }
@action.bound
@@ -315,6 +357,31 @@ export class FilterBox extends React.Component {
getAuthorStatus() { return this._authorFieldStatus; }
getDataStatus() { return this._dataFieldStatus; }
+ getActiveFilters() {
+ console.log(this._authorFieldStatus, this._titleFieldStatus, this._dataFieldStatus);
+ return (
+ <div className="active-filters">
+ {!this._basicWordStatus ? <div className="active-icon container">
+ <div className="active-icon icon">{this.getABCicon()}</div>
+ <div className="active-icon description">Required Words Applied</div>
+ </div> : undefined}
+ {!(this._icons.length === 9) ? <div className="active-icon container">
+ <div className="active-icon icon">{this.getTypeIcon()}</div>
+ <div className="active-icon description">Type Filters Applied</div>
+ </div> : undefined}
+ {!(this._authorFieldStatus && this._dataFieldStatus && this._titleFieldStatus) ?
+ <div className="active-icon container">
+ <div className="active-icon icon">{this.getKeyIcon()}</div>
+ <div className="active-icon description">Field Filters Applied</div>
+ </div> : undefined}
+ {this._collectionStatus ? <div className="active-icon container">
+ <div className="active-icon icon">{this.getColIcon()}</div>
+ <div className="active-icon description">Collection Filters Active</div>
+ </div> : undefined}
+ </div>
+ )
+ }
+
// Useful queries:
// Delegates of a document: {!join from=id to=proto_i}id:{protoId}
// Documents in a collection: {!join from=data_l to=id}id:{collectionProtoId} //id of collections prototype
@@ -323,6 +390,7 @@ export class FilterBox extends React.Component {
<div>
<div style={{ display: "flex", flexDirection: "row-reverse" }}>
<SearchBox />
+ {this.getActiveFilters()}
</div>
{this._filterOpen ? (
<div className="filter-form" onPointerDown={this.stopProp} id="filter-form" style={this._filterOpen ? { display: "flex" } : { display: "none" }}>
@@ -376,7 +444,8 @@ export class FilterBox extends React.Component {
<button className="reset-filter" onClick={this.resetFilters}>Reset Filters</button>
</div>
</div>
- ) : undefined}
+ ) :
+ undefined}
</div>
);
}
diff --git a/src/client/views/search/Pager.tsx b/src/client/views/search/Pager.tsx
index 1c62773b1..9bcfb1676 100644
--- a/src/client/views/search/Pager.tsx
+++ b/src/client/views/search/Pager.tsx
@@ -57,17 +57,17 @@ export class Pager extends React.Component {
return (
<div className="search-pager">
<div className="search-arrows">
- <div className="arrow"
- onPointerDown={this.onLeftClick} style={SearchBox.Instance._pageNum === 0 ? { opacity: .2 } : this._leftHover ? { opacity: 1 } : { opacity: .7 }}
- onMouseEnter={this.mouseInLeft} onMouseOut={this.mouseOutLeft}>
+ <div className = "arrow"
+ onPointerDown = {this.onLeftClick} style = {SearchBox.Instance._pageNum === 0 ? {opacity: .2} : this._leftHover ? {opacity: 1} : {opacity: .7}}
+ onMouseEnter = {this.mouseInLeft} onMouseLeave = {this.mouseOutLeft}>
<FontAwesomeIcon className="fontawesome-icon" icon={faArrowCircleLeft} />
</div>
<div className="pager-title">
page {SearchBox.Instance._pageNum + 1} of {SearchBox.Instance._maxNum}
</div>
- <div className="arrow"
- onPointerDown={this.onRightClick} style={SearchBox.Instance._pageNum === SearchBox.Instance._maxNum - 1 ? { opacity: .2 } : this._rightHover ? { opacity: 1 } : { opacity: .7 }}
- onMouseEnter={this.mouseInRight} onMouseOut={this.mouseOutRight}>
+ <div className = "arrow"
+ onPointerDown = {this.onRightClick} style = {SearchBox.Instance._pageNum === SearchBox.Instance._maxNum-1 ? {opacity: .2} : this._rightHover ? {opacity: 1} : {opacity: .7}}
+ onMouseEnter = {this.mouseInRight} onMouseLeave = {this.mouseOutRight}>
<FontAwesomeIcon className="fontawesome-icon" icon={faArrowCircleRight} />
</div>
</div>
diff --git a/src/client/views/search/SearchBox.scss b/src/client/views/search/SearchBox.scss
index 2a27bbe62..7541b328a 100644
--- a/src/client/views/search/SearchBox.scss
+++ b/src/client/views/search/SearchBox.scss
@@ -46,9 +46,10 @@
display: flex;
flex-direction: column;
margin-right: 72px;
- height: 560px;
- overflow: hidden;
- overflow-y: auto;
+ // height: 560px;
+ height: 100%;
+ // overflow: hidden;
+ // overflow-y: auto;
.no-result {
width: 500px;
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index f53a4e34f..dc21e4a3c 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,6 @@ export class SearchBox extends React.Component {
@action.bound
closeSearch = () => {
- console.log("closing search");
FilterBox.Instance.closeFilter();
this.closeResults();
}
@@ -198,9 +196,9 @@ export class SearchBox extends React.Component {
) :
this._openNoResults ? (<div className="no-result">No Search Results</div>) : null}
</div>
- {/* <div style={this._results.length !== 0 ? { display: "flex" } : { display: "none" }}>
- <Pager />
- </div> */}
+ <div style={this._results.length !== 0 ? { display: "flex" } : { display: "none" }}>
+ {/* <Pager /> */}
+ </div>
</div>
);
}
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 5160d9469..f4ea3ee09 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;
@@ -69,18 +71,63 @@ export class SelectorContextMenu extends React.Component<SearchItemProps> {
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 onClick={this.getOnClick(doc)}>{doc.col.title}</a>
+ </div>;
+ })}
</div>
);
}
}
+export interface LinkMenuProps {
+ doc1: Doc;
+ doc2: Doc;
+}
+
+@observer
+export class LinkContextMenu extends React.Component<LinkMenuProps> {
+
+ highlightDoc = (doc: Doc) => {
+ return () => {
+ doc.libraryBrush = true;
+ };
+ }
+
+ unHighlightDoc = (doc: Doc) => {
+ return () => {
+ doc.libraryBrush = false;
+ };
+ }
+
+ getOnClick(col: Doc) {
+ return () => {
+ CollectionDockingView.Instance.AddRightSplit(col, undefined);
+ };
+ }
+
+ render() {
+ return (
+ <div className="parents">
+ <p className="contexts">Anchors:</p>
+ <div className = "collection"><a onMouseEnter = {this.highlightDoc(this.props.doc1)} onMouseLeave = {this.unHighlightDoc(this.props.doc1)} onClick = {this.getOnClick(this.props.doc1)}>Doc 1: {this.props.doc2.title}</a></div>
+ <div><a onMouseEnter = {this.highlightDoc(this.props.doc2)} onMouseLeave = {this.unHighlightDoc(this.props.doc2)} onClick = {this.getOnClick(this.props.doc2)}>Doc 2: {this.props.doc1.title}</a></div>
+ </div>
+ )
+ }
+
+}
+
@observer
export class SearchItem extends React.Component<SearchItemProps> {
@@ -89,10 +136,56 @@ export class SearchItem extends React.Component<SearchItemProps> {
onClick = () => {
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 +197,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 +214,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,45 +225,65 @@ 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>
<div className="searchBox-instances">
- <SelectorContextMenu {...this.props} />
+ {this.props.doc.type === DocTypes.LINK ? <LinkContextMenu doc1 = {Cast(this.props.doc.anchor1, Doc, new Doc())} doc2 = {Cast(this.props.doc.anchor2, Doc, new Doc())}/> :
+ <SelectorContextMenu {...this.props} /> }
</div>
</div>
);
diff --git a/src/client/views/search/SelectorContextMenu.scss b/src/client/views/search/SelectorContextMenu.scss
index 49f77b9bf..48cacc608 100644
--- a/src/client/views/search/SelectorContextMenu.scss
+++ b/src/client/views/search/SelectorContextMenu.scss
@@ -3,6 +3,7 @@
.parents {
background: $lighter-alt-accent;
padding: 10px;
+ // width: 300px;
.contexts {
text-transform: uppercase;
diff --git a/src/client/views/search/ToggleBar.tsx b/src/client/views/search/ToggleBar.tsx
index 178578c5c..a30104089 100644
--- a/src/client/views/search/ToggleBar.tsx
+++ b/src/client/views/search/ToggleBar.tsx
@@ -59,6 +59,7 @@ export class ToggleBar extends React.Component<ToggleBarProps>{
this._forwardTimeline.play();
this._forwardTimeline.reverse();
this.props.handleChange();
+ console.log(this.props.getStatus())
}
@action.bound