From 2352407ef1722031df20e51f3dce7aff6f3f6c00 Mon Sep 17 00:00:00 2001 From: andrewdkim Date: Sat, 22 Feb 2020 13:08:50 -0500 Subject: initial --- src/client/documents/DocumentTypes.ts | 3 ++- src/client/documents/Documents.ts | 10 ++++++++++ src/client/views/nodes/DocumentContentsView.tsx | 4 +++- src/server/authentication/models/current_user_utils.ts | 3 +++ 4 files changed, 18 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index df056f3e0..e02382661 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -27,5 +27,6 @@ export enum DocumentType { DOCULINK = "doculink", PDFANNO = "pdfanno", INK = "ink", - DOCUMENT = "document" + DOCUMENT = "document", + SEARCH = "search", } \ No newline at end of file diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 4b5152224..622486435 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -44,6 +44,8 @@ import { ComputedField, ScriptField } from "../../new_fields/ScriptField"; import { ProxyField } from "../../new_fields/Proxy"; import { DocumentType } from "./DocumentTypes"; import { RecommendationsBox } from "../views/RecommendationsBox"; +import { SearchDocBox } from "../views/SearchDocBox"; + //import { PresBox } from "../views/nodes/PresBox"; //import { PresField } from "../../new_fields/PresField"; import { LinkFollowBox } from "../views/linking/LinkFollowBox"; @@ -255,6 +257,10 @@ export namespace Docs { [DocumentType.INK, { layout: { view: InkingStroke, dataField: data }, options: { backgroundColor: "transparent" } + }], + [DocumentType.SEARCH, { + layout: { view: SearchDocBox }, + options: { width: 200, height: 200 }, }] ]); @@ -588,6 +594,10 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.RECOMMENDATION), new List(data), options); } + export function SearchDocument(data: Doc[], options: DocumentOptions = {}) { + return InstanceFromProto(Prototypes.get(DocumentType.SEARCH), new List(data), options); + } + export type DocConfig = { doc: Doc, initialWidth?: number, diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 3b1a86d32..15dd1b29f 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -34,6 +34,8 @@ import { WebBox } from "./WebBox"; import { InkingStroke } from "../InkingStroke"; import React = require("react"); import { RecommendationsBox } from "../RecommendationsBox"; +import { SearchDocBox } from "../SearchDocBox"; + import { TraceMobx } from "../../../new_fields/util"; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? @@ -103,7 +105,7 @@ export class DocumentContentsView extends React.Component !buttons || !buttons.includes(d.title)).map(data => Docs.Create.FontIconDocument({ _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, _dropAction: data.click ? "copy" : undefined, title: data.title, icon: data.icon, ignoreClick: data.ignoreClick, -- cgit v1.2.3-70-g09d2 From fd7f4618f23ee547d8dd14d54172085875058667 Mon Sep 17 00:00:00 2001 From: andrewdkim Date: Sat, 22 Feb 2020 13:52:36 -0500 Subject: push --- package-lock.json | 4 ++-- solr-8.3.1/bin/solr-8983.pid | 2 +- solr-8.3.1/server/tmp/start_1935456665153398890.properties | 11 ----------- solr-8.3.1/server/tmp/start_5098042466590842962.properties | 11 ----------- solr-8.3.1/server/tmp/start_5201032335657884982.properties | 11 ----------- solr-8.3.1/server/tmp/start_5906520416860122978.properties | 11 ----------- solr-8.3.1/server/tmp/start_5982280610074344638.properties | 11 ----------- solr-8.3.1/server/tmp/start_8210707001248201939.properties | 11 ----------- src/client/documents/Documents.ts | 4 ++-- src/server/authentication/models/current_user_utils.ts | 2 +- 10 files changed, 6 insertions(+), 72 deletions(-) delete mode 100644 solr-8.3.1/server/tmp/start_1935456665153398890.properties delete mode 100644 solr-8.3.1/server/tmp/start_5098042466590842962.properties delete mode 100644 solr-8.3.1/server/tmp/start_5201032335657884982.properties delete mode 100644 solr-8.3.1/server/tmp/start_5906520416860122978.properties delete mode 100644 solr-8.3.1/server/tmp/start_5982280610074344638.properties delete mode 100644 solr-8.3.1/server/tmp/start_8210707001248201939.properties (limited to 'src') diff --git a/package-lock.json b/package-lock.json index 049c91fcf..833710fe7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16239,7 +16239,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { "safe-buffer": "~5.1.0" @@ -18560,7 +18560,7 @@ }, "wrap-ansi": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "requires": { "string-width": "^1.0.1", diff --git a/solr-8.3.1/bin/solr-8983.pid b/solr-8.3.1/bin/solr-8983.pid index a6905f8ba..d1b546ea3 100644 --- a/solr-8.3.1/bin/solr-8983.pid +++ b/solr-8.3.1/bin/solr-8983.pid @@ -1 +1 @@ -999 +7100 diff --git a/solr-8.3.1/server/tmp/start_1935456665153398890.properties b/solr-8.3.1/server/tmp/start_1935456665153398890.properties deleted file mode 100644 index a694ae90a..000000000 --- a/solr-8.3.1/server/tmp/start_1935456665153398890.properties +++ /dev/null @@ -1,11 +0,0 @@ -#start.jar properties -#Thu Jan 09 14:51:58 UTC 2020 -java.version.platform=8 -java.version=1.8.0_211 -java.version.micro=0 -jetty.home=C\:\\gitstuff\\GitCode\\Dash-Web\\solr-8.3.1\\server -java.version.minor=8 -jetty.home.uri=file\:///C\:/gitstuff/GitCode/Dash-Web/solr-8.3.1/server -jetty.base=C\:\\gitstuff\\GitCode\\Dash-Web\\solr-8.3.1\\server -java.version.major=1 -jetty.base.uri=file\:///C\:/gitstuff/GitCode/Dash-Web/solr-8.3.1/server diff --git a/solr-8.3.1/server/tmp/start_5098042466590842962.properties b/solr-8.3.1/server/tmp/start_5098042466590842962.properties deleted file mode 100644 index 194d8ff5c..000000000 --- a/solr-8.3.1/server/tmp/start_5098042466590842962.properties +++ /dev/null @@ -1,11 +0,0 @@ -#start.jar properties -#Thu Jan 09 23:36:29 UTC 2020 -java.version.platform=8 -java.version=1.8.0_131 -java.version.micro=0 -jetty.home=C\:\\Users\\avd\\Desktop\\Sam\\Dash-Web\\solr-8.3.1\\server -java.version.minor=8 -jetty.home.uri=file\:///C\:/Users/avd/Desktop/Sam/Dash-Web/solr-8.3.1/server -jetty.base=C\:\\Users\\avd\\Desktop\\Sam\\Dash-Web\\solr-8.3.1\\server -java.version.major=1 -jetty.base.uri=file\:///C\:/Users/avd/Desktop/Sam/Dash-Web/solr-8.3.1/server diff --git a/solr-8.3.1/server/tmp/start_5201032335657884982.properties b/solr-8.3.1/server/tmp/start_5201032335657884982.properties deleted file mode 100644 index e3a72dc76..000000000 --- a/solr-8.3.1/server/tmp/start_5201032335657884982.properties +++ /dev/null @@ -1,11 +0,0 @@ -#start.jar properties -#Wed Jan 08 17:27:07 UTC 2020 -java.version.platform=8 -java.version=1.8.0_131 -java.version.micro=0 -jetty.home=C\:\\Users\\avd\\Desktop\\Sam\\Dash-Web\\solr-8.3.1\\server -java.version.minor=8 -jetty.home.uri=file\:///C\:/Users/avd/Desktop/Sam/Dash-Web/solr-8.3.1/server -jetty.base=C\:\\Users\\avd\\Desktop\\Sam\\Dash-Web\\solr-8.3.1\\server -java.version.major=1 -jetty.base.uri=file\:///C\:/Users/avd/Desktop/Sam/Dash-Web/solr-8.3.1/server diff --git a/solr-8.3.1/server/tmp/start_5906520416860122978.properties b/solr-8.3.1/server/tmp/start_5906520416860122978.properties deleted file mode 100644 index 4177968f4..000000000 --- a/solr-8.3.1/server/tmp/start_5906520416860122978.properties +++ /dev/null @@ -1,11 +0,0 @@ -#start.jar properties -#Wed Jan 08 14:30:05 UTC 2020 -java.version.platform=8 -java.version=1.8.0_211 -java.version.micro=0 -jetty.home=c\:\\gitstuff\\GitCode\\Dash-Web\\solr-8.3.1\\server -java.version.minor=8 -jetty.home.uri=file\:///c\:/gitstuff/GitCode/Dash-Web/solr-8.3.1/server -jetty.base=c\:\\gitstuff\\GitCode\\Dash-Web\\solr-8.3.1\\server -java.version.major=1 -jetty.base.uri=file\:///c\:/gitstuff/GitCode/Dash-Web/solr-8.3.1/server diff --git a/solr-8.3.1/server/tmp/start_5982280610074344638.properties b/solr-8.3.1/server/tmp/start_5982280610074344638.properties deleted file mode 100644 index 840417082..000000000 --- a/solr-8.3.1/server/tmp/start_5982280610074344638.properties +++ /dev/null @@ -1,11 +0,0 @@ -#start.jar properties -#Fri Dec 13 19:19:27 UTC 2019 -java.version.platform=8 -java.version=1.8.0_131 -java.version.micro=0 -jetty.home=C\:\\Users\\avd\\Desktop\\Sam\\Dash-Web\\solr-8.3.1\\server -java.version.minor=8 -jetty.home.uri=file\:///C\:/Users/avd/Desktop/Sam/Dash-Web/solr-8.3.1/server -jetty.base=C\:\\Users\\avd\\Desktop\\Sam\\Dash-Web\\solr-8.3.1\\server -java.version.major=1 -jetty.base.uri=file\:///C\:/Users/avd/Desktop/Sam/Dash-Web/solr-8.3.1/server diff --git a/solr-8.3.1/server/tmp/start_8210707001248201939.properties b/solr-8.3.1/server/tmp/start_8210707001248201939.properties deleted file mode 100644 index aebc17bdc..000000000 --- a/solr-8.3.1/server/tmp/start_8210707001248201939.properties +++ /dev/null @@ -1,11 +0,0 @@ -#start.jar properties -#Thu Jan 16 20:33:22 UTC 2020 -java.version.platform=8 -java.version=1.8.0_211 -java.version.micro=0 -jetty.home=C\:\\gitstuff\\GitCode\\Dash-Web\\solr-8.3.1\\server -java.version.minor=8 -jetty.home.uri=file\:///C\:/gitstuff/GitCode/Dash-Web/solr-8.3.1/server -jetty.base=C\:\\gitstuff\\GitCode\\Dash-Web\\solr-8.3.1\\server -java.version.major=1 -jetty.base.uri=file\:///C\:/gitstuff/GitCode/Dash-Web/solr-8.3.1/server diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 622486435..144554cbc 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -594,8 +594,8 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.RECOMMENDATION), new List(data), options); } - export function SearchDocument(data: Doc[], options: DocumentOptions = {}) { - return InstanceFromProto(Prototypes.get(DocumentType.SEARCH), new List(data), options); + export function SearchDocument(options: DocumentOptions = {}) { + return InstanceFromProto(Prototypes.get(DocumentType.SEARCH), new List(), options); } export type DocConfig = { diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 009d013fe..ec6fdc021 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -64,7 +64,7 @@ export class CurrentUserUtils { { title: "use eraser", icon: "eraser", click: 'activateEraser(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this);', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "pink", activePen: doc }, { title: "use scrubber", icon: "eraser", click: 'activateScrubber(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this);', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "green", activePen: doc }, { title: "use drag", icon: "mouse-pointer", click: 'deactivateInk();this.activePen.pen = this;', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "white", activePen: doc }, - { title: "cat image", icon: "cat", ignoreClick: true, drag: 'Docs.Create.SearchDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { _width: 200, title: "an image of a cat" })' }, + { title: "searc", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.SearchDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { _width: 200, title: "an image of a cat" })' }, ]; -- cgit v1.2.3-70-g09d2 From 525766cd02ec38174334e62709c36a3b0caa208a Mon Sep 17 00:00:00 2001 From: andrewdkim Date: Sat, 22 Feb 2020 14:06:39 -0500 Subject: new file --- src/client/views/SearchDocBox.tsx | 198 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 src/client/views/SearchDocBox.tsx (limited to 'src') diff --git a/src/client/views/SearchDocBox.tsx b/src/client/views/SearchDocBox.tsx new file mode 100644 index 000000000..596129c73 --- /dev/null +++ b/src/client/views/SearchDocBox.tsx @@ -0,0 +1,198 @@ +import { observer } from "mobx-react"; +import React = require("react"); +import { observable, action, computed, runInAction } from "mobx"; +import Measure from "react-measure"; +import "./RecommendationsBox.scss"; +import { Doc, DocListCast, WidthSym, HeightSym } from "../../new_fields/Doc"; +import { DocumentIcon } from "./nodes/DocumentIcon"; +import { StrCast, NumCast } from "../../new_fields/Types"; +import { returnFalse, emptyFunction, returnEmptyString, returnOne } from "../../Utils"; +import { Transform } from "../util/Transform"; +import { ObjectField } from "../../new_fields/ObjectField"; +import { DocumentView } from "./nodes/DocumentView"; +import { DocumentType } from '../documents/DocumentTypes'; +import { ClientRecommender } from "../ClientRecommender"; +import { DocServer } from "../DocServer"; +import { Id } from "../../new_fields/FieldSymbols"; +import { FieldView, FieldViewProps } from "./nodes/FieldView"; +import { DocumentManager } from "../util/DocumentManager"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { library } from "@fortawesome/fontawesome-svg-core"; +import { faBullseye, faLink } from "@fortawesome/free-solid-svg-icons"; +import { DocUtils } from "../documents/Documents"; + +export interface RecProps { + documents: { preview: Doc, similarity: number }[]; + node: Doc; +} + +library.add(faBullseye, faLink); + +@observer +export class SearchDocBox extends React.Component { + + 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); + } + + @action + private DocumentIcon(doc: Doc) { + let layoutresult = StrCast(doc.type); + let renderDoc = doc; + //let box: number[] = []; + if (layoutresult.indexOf(DocumentType.COL) !== -1) { + renderDoc = Doc.MakeDelegate(renderDoc); + } + let returnXDimension = () => 150; + let returnYDimension = () => 150; + let scale = () => returnXDimension() / NumCast(renderDoc.nativeWidth, returnXDimension()); + //let scale = () => 1; + let newRenderDoc = Doc.MakeAlias(renderDoc); /// newRenderDoc -> renderDoc -> render"data"Doc -> TextProt + newRenderDoc.height = NumCast(this.props.Document.documentIconHeight); + newRenderDoc.autoHeight = false; + const docview =
+ +
; + return docview; + + } + + // @action + // closeMenu = () => { + // this._display = false; + // this.previewDocs.forEach(doc => DocServer.DeleteDocument(doc[Id])); + // this.previewDocs = []; + // } + + // @action + // resetDocuments = () => { + // this._documents = []; + // } + + // @action + // displayRecommendations(x: number, y: number) { + // this._pageX = x; + // this._pageY = y; + // this._display = true; + // } + + static readonly buffer = 20; + + // get pageX() { + // const x = this._pageX; + // if (x < 0) { + // return 0; + // } + // const width = this._width; + // if (x + width > window.innerWidth - RecommendationsBox.buffer) { + // return window.innerWidth - RecommendationsBox.buffer - width; + // } + // return x; + // } + + // get pageY() { + // const y = this._pageY; + // if (y < 0) { + // return 0; + // } + // const height = this._height; + // if (y + height > window.innerHeight - RecommendationsBox.buffer) { + // return window.innerHeight - RecommendationsBox.buffer - height; + // } + // return y; + // } + + // get createDocViews() { + // return DocListCast(this.props.Document.data).map(doc => { + // return ( + //
+ // + // {this.DocumentIcon(doc)} + // + // {NumCast(doc.score).toFixed(4)} + //
DocumentManager.Instance.jumpToDocument(doc, false)}> + // + //
+ //
DocUtils.MakeLink({ doc: this.props.Document.sourceDoc as Doc }, { doc: doc }, "User Selected Link", "Generated from Recommender", undefined)}> + // + //
+ //
+ // ); + // }); + // } + + componentDidMount() { //TODO: invoking a computedFn from outside an reactive context won't be memoized, unless keepAlive is set + runInAction(() => { + if (this._docViews.length === 0) { + this._docViews = DocListCast(this.props.Document.data).map(doc => { + return ( +
+ + {this.DocumentIcon(doc)} + + {NumCast(doc.score).toFixed(4)} +
DocumentManager.Instance.jumpToDocument(doc, false)}> + +
+
DocUtils.MakeLink({ doc: this.props.Document.sourceDoc as Doc }, { doc: doc }, "User Selected Link", "Generated from Recommender", undefined)}> + +
+
+ ); + }); + } + }); + } + + render() { //TODO: Invariant violation: max depth exceeded error. Occurs when images are rendered. + // if (!this._display) { + // return null; + // } + // let style = { left: this.pageX, top: this.pageY }; + //const transform = "translate(" + (NumCast(this.props.node.x) + 350) + "px, " + NumCast(this.props.node.y) + "px" + // let title = StrCast((this.props.Document.sourceDoc as Doc).title); + // if (title.length > 15) { + // title = title.substring(0, 15) + "..."; + // } + return ( +
+ {this._docViews} +
+ ); + } + // + // +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From ad83dfcfaea5a6b525351b022158ebf5ff1f8c2f Mon Sep 17 00:00:00 2001 From: andrewdkim Date: Sat, 22 Feb 2020 15:00:52 -0500 Subject: replacing search drag functionality --- solr-8.3.1/bin/solr-8983.pid | 2 +- src/client/documents/DocumentTypes.ts | 2 +- src/client/documents/Documents.ts | 7 +-- src/client/views/SearchDocBox.tsx | 54 +++++++++++++--------- src/client/views/search/SearchBox.scss | 2 +- src/client/views/search/SearchBox.tsx | 3 +- .../authentication/models/current_user_utils.ts | 2 +- 7 files changed, 42 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/solr-8.3.1/bin/solr-8983.pid b/solr-8.3.1/bin/solr-8983.pid index d1b546ea3..2dfa22ed7 100644 --- a/solr-8.3.1/bin/solr-8983.pid +++ b/solr-8.3.1/bin/solr-8983.pid @@ -1 +1 @@ -7100 +13872 diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index e02382661..adc61aa80 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -28,5 +28,5 @@ export enum DocumentType { PDFANNO = "pdfanno", INK = "ink", DOCUMENT = "document", - SEARCH = "search", + SEARCHBOX = "searchbox", } \ No newline at end of file diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 144554cbc..86e459561 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -46,6 +46,7 @@ import { DocumentType } from "./DocumentTypes"; import { RecommendationsBox } from "../views/RecommendationsBox"; import { SearchDocBox } from "../views/SearchDocBox"; + //import { PresBox } from "../views/nodes/PresBox"; //import { PresField } from "../../new_fields/PresField"; import { LinkFollowBox } from "../views/linking/LinkFollowBox"; @@ -258,7 +259,7 @@ export namespace Docs { layout: { view: InkingStroke, dataField: data }, options: { backgroundColor: "transparent" } }], - [DocumentType.SEARCH, { + [DocumentType.SEARCHBOX, { layout: { view: SearchDocBox }, options: { width: 200, height: 200 }, }] @@ -594,8 +595,8 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.RECOMMENDATION), new List(data), options); } - export function SearchDocument(options: DocumentOptions = {}) { - return InstanceFromProto(Prototypes.get(DocumentType.SEARCH), new List(), options); + export function SearchDocument(documents: Array, options: DocumentOptions = {}) { + return InstanceFromProto(Prototypes.get(DocumentType.SEARCHBOX), new List(documents), options); } export type DocConfig = { diff --git a/src/client/views/SearchDocBox.tsx b/src/client/views/SearchDocBox.tsx index 596129c73..c64b7285a 100644 --- a/src/client/views/SearchDocBox.tsx +++ b/src/client/views/SearchDocBox.tsx @@ -19,7 +19,8 @@ import { DocumentManager } from "../util/DocumentManager"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { library } from "@fortawesome/fontawesome-svg-core"; import { faBullseye, faLink } from "@fortawesome/free-solid-svg-icons"; -import { DocUtils } from "../documents/Documents"; +import { DocUtils, Docs } from "../documents/Documents"; +import { ContentFittingDocumentView } from "./nodes/ContentFittingDocumentView"; export interface RecProps { documents: { preview: Doc, similarity: number }[]; @@ -156,27 +157,33 @@ export class SearchDocBox extends React.Component { componentDidMount() { //TODO: invoking a computedFn from outside an reactive context won't be memoized, unless keepAlive is set runInAction(() => { - if (this._docViews.length === 0) { - this._docViews = DocListCast(this.props.Document.data).map(doc => { - return ( -
- - {this.DocumentIcon(doc)} - - {NumCast(doc.score).toFixed(4)} -
DocumentManager.Instance.jumpToDocument(doc, false)}> - -
-
DocUtils.MakeLink({ doc: this.props.Document.sourceDoc as Doc }, { doc: doc }, "User Selected Link", "Generated from Recommender", undefined)}> - -
-
- ); - }); - } + //if (this._docViews.length === 0) { + //this._docViews = + this.content = (Docs.Create.TreeDocument(DocListCast(Doc.GetProto(this.props.Document).data), { _width: 200, _height: 400, backgroundColor: "grey", title: `Search Docs: "Results"` })); + + // this._docViews = DocListCast(this.props.Document.data).map(doc => { + // return ( + //
+ // + // {this.DocumentIcon(doc)} + // + // {NumCast(doc.score).toFixed(4)} + //
DocumentManager.Instance.jumpToDocument(doc, false)}> + // + //
+ //
DocUtils.MakeLink({ doc: this.props.Document.sourceDoc as Doc }, { doc: doc }, "User Selected Link", "Generated from Recommender", undefined)}> + // + //
+ //
+ // ); + // }); + //} }); } + @observable + private content: Doc | undefined; + render() { //TODO: Invariant violation: max depth exceeded error. Occurs when images are rendered. // if (!this._display) { // return null; @@ -188,9 +195,12 @@ export class SearchDocBox extends React.Component { // title = title.substring(0, 15) + "..."; // } return ( -
- {this._docViews} -
+ //
+ + + //
); } // diff --git a/src/client/views/search/SearchBox.scss b/src/client/views/search/SearchBox.scss index f492ea773..11714748a 100644 --- a/src/client/views/search/SearchBox.scss +++ b/src/client/views/search/SearchBox.scss @@ -19,7 +19,7 @@ padding-left: 2px; padding-right: 2px; - .searchBox-barChild { +.searchBox-barChild { &.searchBox-collection { flex: 0 1 auto; diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index be13dae03..7628297c0 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -234,7 +234,8 @@ export class SearchBox extends React.Component { y += 300; } } - return Docs.Create.TreeDocument(docs, { _width: 200, _height: 400, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` }); + //return Docs.Create.TreeDocument(docs, { _width: 200, _height: 400, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` }); + return Docs.Create.SearchDocument(docs, { _width: 200, _height: 400, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` }); } @action.bound diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index ec6fdc021..58958f1fc 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -64,7 +64,7 @@ export class CurrentUserUtils { { title: "use eraser", icon: "eraser", click: 'activateEraser(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this);', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "pink", activePen: doc }, { title: "use scrubber", icon: "eraser", click: 'activateScrubber(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this);', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "green", activePen: doc }, { title: "use drag", icon: "mouse-pointer", click: 'deactivateInk();this.activePen.pen = this;', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "white", activePen: doc }, - { title: "searc", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.SearchDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { _width: 200, title: "an image of a cat" })' }, + { title: "search", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.SearchDocument({ _width: 200, title: "an image of a cat" })' }, ]; -- cgit v1.2.3-70-g09d2 From ac59127b264386bdfbf6443822984d002afb7da9 Mon Sep 17 00:00:00 2001 From: andrewdkim Date: Sun, 23 Feb 2020 16:47:40 -0500 Subject: css menu --- src/client/documents/Documents.ts | 2 + src/client/views/SearchDocBox.tsx | 213 +++++++++++----------------------- src/client/views/search/SearchBox.tsx | 2 +- 3 files changed, 72 insertions(+), 145 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 86e459561..8ade14251 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -146,6 +146,8 @@ export interface DocumentOptions { flexDirection?: "unset" | "row" | "column" | "row-reverse" | "column-reverse"; selectedIndex?: number; syntaxColor?: string; // can be applied to text for syntax highlighting all matches in the text + searchText?: string, //for searchbox + } class EmptyBox { diff --git a/src/client/views/SearchDocBox.tsx b/src/client/views/SearchDocBox.tsx index c64b7285a..da0872c43 100644 --- a/src/client/views/SearchDocBox.tsx +++ b/src/client/views/SearchDocBox.tsx @@ -2,10 +2,10 @@ import { observer } from "mobx-react"; import React = require("react"); import { observable, action, computed, runInAction } from "mobx"; import Measure from "react-measure"; -import "./RecommendationsBox.scss"; +import "./SearchBoxDoc.scss"; import { Doc, DocListCast, WidthSym, HeightSym } from "../../new_fields/Doc"; import { DocumentIcon } from "./nodes/DocumentIcon"; -import { StrCast, NumCast } from "../../new_fields/Types"; +import { StrCast, NumCast, BoolCast } from "../../new_fields/Types"; import { returnFalse, emptyFunction, returnEmptyString, returnOne } from "../../Utils"; import { Transform } from "../util/Transform"; import { ObjectField } from "../../new_fields/ObjectField"; @@ -21,13 +21,16 @@ import { library } from "@fortawesome/fontawesome-svg-core"; import { faBullseye, faLink } from "@fortawesome/free-solid-svg-icons"; import { DocUtils, Docs } from "../documents/Documents"; import { ContentFittingDocumentView } from "./nodes/ContentFittingDocumentView"; +import { EditableView } from "./EditableView"; 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 { @@ -45,164 +48,86 @@ export class SearchDocBox extends React.Component { constructor(props: FieldViewProps) { super(props); + this.editingMetadata = this.editingMetadata || false; } - @action - private DocumentIcon(doc: Doc) { - let layoutresult = StrCast(doc.type); - let renderDoc = doc; - //let box: number[] = []; - if (layoutresult.indexOf(DocumentType.COL) !== -1) { - renderDoc = Doc.MakeDelegate(renderDoc); - } - let returnXDimension = () => 150; - let returnYDimension = () => 150; - let scale = () => returnXDimension() / NumCast(renderDoc.nativeWidth, returnXDimension()); - //let scale = () => 1; - let newRenderDoc = Doc.MakeAlias(renderDoc); /// newRenderDoc -> renderDoc -> render"data"Doc -> TextProt - newRenderDoc.height = NumCast(this.props.Document.documentIconHeight); - newRenderDoc.autoHeight = false; - const docview =
- -
; - return docview; + @computed + private get editingMetadata() { + return BoolCast(this.props.Document.editingMetadata); } - // @action - // closeMenu = () => { - // this._display = false; - // this.previewDocs.forEach(doc => DocServer.DeleteDocument(doc[Id])); - // this.previewDocs = []; - // } - - // @action - // resetDocuments = () => { - // this._documents = []; - // } - - // @action - // displayRecommendations(x: number, y: number) { - // this._pageX = x; - // this._pageY = y; - // this._display = true; - // } + @computed + private set editingMetadata(value: boolean) { + this.props.Document.editingMetadata = value; + } static readonly buffer = 20; - // get pageX() { - // const x = this._pageX; - // if (x < 0) { - // return 0; - // } - // const width = this._width; - // if (x + width > window.innerWidth - RecommendationsBox.buffer) { - // return window.innerWidth - RecommendationsBox.buffer - width; - // } - // return x; - // } - - // get pageY() { - // const y = this._pageY; - // if (y < 0) { - // return 0; - // } - // const height = this._height; - // if (y + height > window.innerHeight - RecommendationsBox.buffer) { - // return window.innerHeight - RecommendationsBox.buffer - height; - // } - // return y; - // } - - // get createDocViews() { - // return DocListCast(this.props.Document.data).map(doc => { - // return ( - //
- // - // {this.DocumentIcon(doc)} - // - // {NumCast(doc.score).toFixed(4)} - //
DocumentManager.Instance.jumpToDocument(doc, false)}> - // - //
- //
DocUtils.MakeLink({ doc: this.props.Document.sourceDoc as Doc }, { doc: doc }, "User Selected Link", "Generated from Recommender", undefined)}> - // - //
- //
- // ); - // }); - // } - - componentDidMount() { //TODO: invoking a computedFn from outside an reactive context won't be memoized, unless keepAlive is set + componentDidMount() { runInAction(() => { - //if (this._docViews.length === 0) { - //this._docViews = - this.content = (Docs.Create.TreeDocument(DocListCast(Doc.GetProto(this.props.Document).data), { _width: 200, _height: 400, backgroundColor: "grey", title: `Search Docs: "Results"` })); - - // this._docViews = DocListCast(this.props.Document.data).map(doc => { - // return ( - //
- // - // {this.DocumentIcon(doc)} - // - // {NumCast(doc.score).toFixed(4)} - //
DocumentManager.Instance.jumpToDocument(doc, false)}> - // - //
- //
DocUtils.MakeLink({ doc: this.props.Document.sourceDoc as Doc }, { doc: doc }, "User Selected Link", "Generated from Recommender", undefined)}> - // - //
- //
- // ); - // }); - //} + this.content = (Docs.Create.TreeDocument(DocListCast(Doc.GetProto(this.props.Document).data), { _width: 200, _height: 400, _chromeStatus: "disabled", title: `Search Docs: "Results"` })); + this.query = StrCast(this.props.Document.searchText); }); } @observable private content: Doc | undefined; - render() { //TODO: Invariant violation: max depth exceeded error. Occurs when images are rendered. - // if (!this._display) { - // return null; - // } - // let style = { left: this.pageX, top: this.pageY }; - //const transform = "translate(" + (NumCast(this.props.node.x) + 350) + "px, " + NumCast(this.props.node.y) + "px" - // let title = StrCast((this.props.Document.sourceDoc as Doc).title); - // if (title.length > 15) { - // title = title.substring(0, 15) + "..."; - // } + @action + updateKey = (newKey: string) => { + this.query = newKey; + //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; + } + + render() { + const isEditing = this.editingMetadata; + console.log(isEditing); return ( - //
- - - //
+
+
this.editingMetadata = !this.editingMetadata)} + /> +
+ ""} + /> +
+
+ + +
+
); } - // - // + } \ No newline at end of file diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 7628297c0..9af8829fa 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -235,7 +235,7 @@ export class SearchBox extends React.Component { } } //return Docs.Create.TreeDocument(docs, { _width: 200, _height: 400, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` }); - return Docs.Create.SearchDocument(docs, { _width: 200, _height: 400, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` }); + return Docs.Create.SearchDocument(docs, { _width: 200, _height: 400, searchText: this._searchString, title: `Search Docs: "${this._searchString}"` }); } @action.bound -- cgit v1.2.3-70-g09d2 From 6c389c764c39c9b446996cc1a4aa777a9302f677 Mon Sep 17 00:00:00 2001 From: Andy Rickert Date: Mon, 24 Feb 2020 21:58:12 -0500 Subject: researching tentatively works --- package-lock.json | 92 ----------- package.json | 1 - src/client/views/SearchDocBox.tsx | 324 ++++++++++++++++++++++++++++++++++++-- src/server/Recommender.ts | 2 +- 4 files changed, 316 insertions(+), 103 deletions(-) (limited to 'src') diff --git a/package-lock.json b/package-lock.json index 833710fe7..f6b1e80da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -287,17 +287,6 @@ "resolved": "https://registry.npmjs.org/@tensorflow-models/universal-sentence-encoder/-/universal-sentence-encoder-1.2.2.tgz", "integrity": "sha512-fGCl/gwB7jmKCRI2FhgIBeIa/LCSUcjlEcckH2Bc2dIjhJ+2nspp+22lubxcseN6jjrmP42kkXt/reAPe+KJkQ==" }, - "@tensorflow/tfjs": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs/-/tfjs-1.5.2.tgz", - "integrity": "sha512-BCvcbnkE/zMdORIGE7TFAiJU3zLLVUaRv/HyWucVVyHU40oU4L5mGyRXK6RwqU38KmeK3HSI5rUHop4cLNUaRQ==", - "requires": { - "@tensorflow/tfjs-converter": "1.5.2", - "@tensorflow/tfjs-core": "1.5.2", - "@tensorflow/tfjs-data": "1.5.2", - "@tensorflow/tfjs-layers": "1.5.2" - } - }, "@tensorflow/tfjs-converter": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-converter/-/tfjs-converter-1.5.2.tgz", @@ -323,69 +312,6 @@ } } }, - "@tensorflow/tfjs-data": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-data/-/tfjs-data-1.5.2.tgz", - "integrity": "sha512-ruCsTSyH67CADWthgLQlWKh8u8YGEXD+4vsW8uOGdFNcDFLcL0ffy4jsSzIV/X6NdPIWYsvSHmiz57LtgfCFew==", - "requires": { - "@types/node-fetch": "^2.1.2", - "node-fetch": "~2.1.2" - }, - "dependencies": { - "node-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", - "integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=" - } - } - }, - "@tensorflow/tfjs-layers": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-layers/-/tfjs-layers-1.5.2.tgz", - "integrity": "sha512-fn2hi5D1sOKGEgiBCuoU/hTHO87znODweGivIn6x2HMtF1EC39QWroYQBWzJyrWWMOUZZ4nOFR6coA0Fkhc+nA==" - }, - "@tensorflow/tfjs-node": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-node/-/tfjs-node-1.5.2.tgz", - "integrity": "sha512-qihOkKbCLTDcqe3TTDbA9v00PacMzPwhspV8MEHWpohVb7itqQ8cMSE8w38b2oA+FE38c1RI7KOd2qAl5bCNHA==", - "requires": { - "@tensorflow/tfjs": "1.5.2", - "adm-zip": "^0.4.11", - "google-protobuf": "^3.9.2", - "https-proxy-agent": "^2.2.1", - "node-pre-gyp": "0.14.0", - "progress": "^2.0.0", - "rimraf": "^2.6.2", - "tar": "^4.4.6" - }, - "dependencies": { - "node-pre-gyp": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz", - "integrity": "sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==", - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4.4.2" - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "requires": { - "glob": "^7.1.3" - } - } - } - }, "@trendmicro/react-buttons": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@trendmicro/react-buttons/-/react-buttons-1.3.1.tgz", @@ -781,14 +707,6 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.13.tgz", "integrity": "sha512-pMCcqU2zT4TjqYFrWtYHKal7Sl30Ims6ulZ4UFXxI4xbtQqK/qqKwkDoBFCfooRqqmRu9vY3xaJRwxSh673aYg==" }, - "@types/node-fetch": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.4.tgz", - "integrity": "sha512-Oz6id++2qAOFuOlE1j0ouk1dzl3mmI1+qINPNBhi9nt/gVOz0G+13Ao6qjhdF0Ys+eOkhu6JnFmt38bR3H0POQ==", - "requires": { - "@types/node": "*" - } - }, "@types/nodemailer": { "version": "4.6.8", "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-4.6.8.tgz", @@ -6445,11 +6363,6 @@ } } }, - "google-protobuf": { - "version": "3.11.3", - "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.11.3.tgz", - "integrity": "sha512-Sp8E+0AJLxmiPwAk9VH3MkYAmYYheNUhywIyXOS7wvRkqbIYcHtGzJzIYicNqYsqgKmY35F9hxRkI+ZTqTB4Tg==" - }, "googleapis": { "version": "40.0.1", "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-40.0.1.tgz", @@ -13423,11 +13336,6 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" - }, "promise": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", diff --git a/package.json b/package.json index 7e0adfba6..cd97e590c 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,6 @@ "@tensorflow-models/universal-sentence-encoder": "^1.2.2", "@tensorflow/tfjs-converter": "^1.3.2", "@tensorflow/tfjs-core": "^1.5.2", - "@tensorflow/tfjs-node": "^1.5.2", "@trendmicro/react-dropdown": "^1.3.0", "@types/adm-zip": "^0.4.32", "@types/animejs": "^2.0.2", diff --git a/src/client/views/SearchDocBox.tsx b/src/client/views/SearchDocBox.tsx index da0872c43..06d434789 100644 --- a/src/client/views/SearchDocBox.tsx +++ b/src/client/views/SearchDocBox.tsx @@ -2,10 +2,10 @@ import { observer } from "mobx-react"; import React = require("react"); import { observable, action, computed, runInAction } from "mobx"; import Measure from "react-measure"; -import "./SearchBoxDoc.scss"; +//import "./SearchBoxDoc.scss"; import { Doc, DocListCast, WidthSym, HeightSym } from "../../new_fields/Doc"; import { DocumentIcon } from "./nodes/DocumentIcon"; -import { StrCast, NumCast, BoolCast } from "../../new_fields/Types"; +import { StrCast, NumCast, BoolCast, Cast } from "../../new_fields/Types"; import { returnFalse, emptyFunction, returnEmptyString, returnOne } from "../../Utils"; import { Transform } from "../util/Transform"; import { ObjectField } from "../../new_fields/ObjectField"; @@ -22,6 +22,10 @@ import { faBullseye, faLink } from "@fortawesome/free-solid-svg-icons"; import { DocUtils, Docs } from "../documents/Documents"; import { ContentFittingDocumentView } from "./nodes/ContentFittingDocumentView"; import { EditableView } from "./EditableView"; +import { SearchUtil } from "../util/SearchUtil"; +import { SearchItem } from "./search/SearchItem"; +import { FilterBox } from "./search/FilterBox"; +import { SearchBox } from "./search/SearchBox"; export interface RecProps { documents: { preview: Doc, similarity: number }[]; @@ -35,8 +39,6 @@ export const keyPlaceholder = "Query"; @observer export class SearchDocBox extends React.Component { - 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; @@ -49,6 +51,8 @@ export class SearchDocBox extends React.Component { constructor(props: FieldViewProps) { super(props); this.editingMetadata = this.editingMetadata || false; + //SearchBox.Instance = this; + this.resultsScrolled = this.resultsScrolled.bind(this); } @@ -57,7 +61,6 @@ export class SearchDocBox extends React.Component { return BoolCast(this.props.Document.editingMetadata); } - @computed private set editingMetadata(value: boolean) { this.props.Document.editingMetadata = value; } @@ -66,16 +69,32 @@ export class SearchDocBox extends React.Component { componentDidMount() { runInAction(() => { - this.content = (Docs.Create.TreeDocument(DocListCast(Doc.GetProto(this.props.Document).data), { _width: 200, _height: 400, _chromeStatus: "disabled", title: `Search Docs: "Results"` })); 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 = (newKey: string) => { + updateKey = async (newKey: string) => { + if (newKey.length >1){ + let newdocs= await this.getAllResults(this.query) + let things = newdocs.docs + console.log(things); + await runInAction(() => { + this.content=Docs.Create.TreeDocument(things, { _width: 200, _height: 400, _chromeStatus: "disabled", title: `Search Docs:` + this.query }); + }); + } + this.query = newKey; //this.keyRef.current && this.keyRef.current.setIsFocused(false); //this.query.length === 0 && (this.query = keyPlaceholder); @@ -91,6 +110,293 @@ export class SearchDocBox extends React.Component { 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(); + @observable private _openNoResults: boolean = false; + @observable private _visibleElements: JSX.Element[] = []; + + private resultsRef = React.createRef(); + public inputRef = React.createRef(); + + private _isSearch: ("search" | "placeholder" | undefined)[] = []; + private _numTotalResults = -1; + private _endIndex = -1; + + + private _maxSearchIndex: number = 0; + private _curRequest?: Promise = 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) { + 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; + 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(); + 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(); + 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.SearchDocument(docs, { _width: 200, _height: 400, searchText: this._searchString, title: `Search 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) => { + 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 = [
No Search Results
]; + 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(this._numTotalResults === -1 ? 0 : this._numTotalResults); + // indicates if things are placeholders + this._isSearch = Array(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] =
Loading...
; + } + } + 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] = ; + 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] = ; + 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; console.log(isEditing); @@ -109,9 +415,9 @@ export class SearchDocBox extends React.Component { zIndex: 99, }} title={"Add Metadata"} - onClick={action(() => this.editingMetadata = !this.editingMetadata)} + onDoubleClick={action(() => {this.editingMetadata = !this.editingMetadata })} /> -
+
Date: Wed, 26 Feb 2020 17:52:51 -0500 Subject: fixing css and ui --- src/client/views/SearchDocBox.tsx | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/client/views/SearchDocBox.tsx b/src/client/views/SearchDocBox.tsx index 06d434789..5f308ff71 100644 --- a/src/client/views/SearchDocBox.tsx +++ b/src/client/views/SearchDocBox.tsx @@ -69,6 +69,8 @@ export class SearchDocBox extends React.Component { 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})); @@ -86,16 +88,19 @@ export class SearchDocBox extends React.Component { @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); - await runInAction(() => { - this.content=Docs.Create.TreeDocument(things, { _width: 200, _height: 400, _chromeStatus: "disabled", title: `Search Docs:` + this.query }); - }); + 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.query = newKey; + //this.keyRef.current && this.keyRef.current.setIsFocused(false); //this.query.length === 0 && (this.query = keyPlaceholder); return true; @@ -399,9 +404,12 @@ export class SearchDocBox extends React.Component { render() { const isEditing = this.editingMetadata; - console.log(isEditing); return (
+ + s
{ opacity: 1, transition: "0.4s opacity ease", zIndex: 99, + top:0, }} title={"Add Metadata"} - onDoubleClick={action(() => {this.editingMetadata = !this.editingMetadata })} + onClick={action(() => {this.editingMetadata = !this.editingMetadata })} /> -
+
""} />
-
- - -
); } -- cgit v1.2.3-70-g09d2 From 14a2f361c73e468547d48792478e5e7e7e78f4d6 Mon Sep 17 00:00:00 2001 From: vellichora Date: Sat, 29 Feb 2020 13:52:53 -0500 Subject: filter UI --- package-lock.json | 41 +-- src/client/views/SearchDocBox.tsx | 34 +-- src/client/views/search/CheckBox.tsx | 146 +++++----- src/client/views/search/SearchBox.tsx | 47 +++ src/server/ApiManagers/SessionManager.ts | 20 +- src/server/DashSession/DashSessionAgent.ts | 446 ++++++++++++++--------------- src/server/index.ts | 4 +- 7 files changed, 384 insertions(+), 354 deletions(-) (limited to 'src') diff --git a/package-lock.json b/package-lock.json index f6b1e80da..e60950308 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5600,8 +5600,7 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true, - "optional": true + "bundled": true }, "aproba": { "version": "1.2.0", @@ -5619,13 +5618,11 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true, - "optional": true + "bundled": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5638,18 +5635,15 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "concat-map": { "version": "0.0.1", - "bundled": true, - "optional": true + "bundled": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "core-util-is": { "version": "1.0.2", @@ -5752,8 +5746,7 @@ }, "inherits": { "version": "2.0.4", - "bundled": true, - "optional": true + "bundled": true }, "ini": { "version": "1.3.5", @@ -5763,7 +5756,6 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -5776,20 +5768,17 @@ "minimatch": { "version": "3.0.4", "bundled": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true, - "optional": true + "bundled": true }, "minipass": { "version": "2.9.0", "bundled": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -5806,7 +5795,6 @@ "mkdirp": { "version": "0.5.1", "bundled": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -5887,8 +5875,7 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, - "optional": true + "bundled": true }, "object-assign": { "version": "4.1.1", @@ -5898,7 +5885,6 @@ "once": { "version": "1.4.0", "bundled": true, - "optional": true, "requires": { "wrappy": "1" } @@ -5974,8 +5960,7 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true, - "optional": true + "bundled": true }, "safer-buffer": { "version": "2.1.2", @@ -6005,7 +5990,6 @@ "string-width": { "version": "1.0.2", "bundled": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6023,7 +6007,6 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6062,13 +6045,11 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, - "optional": true + "bundled": true }, "yallist": { "version": "3.1.1", - "bundled": true, - "optional": true + "bundled": true } } }, diff --git a/src/client/views/SearchDocBox.tsx b/src/client/views/SearchDocBox.tsx index 5f308ff71..5a76a882f 100644 --- a/src/client/views/SearchDocBox.tsx +++ b/src/client/views/SearchDocBox.tsx @@ -39,6 +39,8 @@ export const keyPlaceholder = "Query"; @observer export class SearchDocBox extends React.Component { + 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; @@ -72,7 +74,7 @@ export class SearchDocBox extends React.Component { 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})); + 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) { @@ -89,16 +91,16 @@ export class SearchDocBox extends React.Component { @action updateKey = async (newKey: string) => { this.query = newKey; - if (newKey.length >1){ - let newdocs= await this.getAllResults(this.query) + 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.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); @@ -161,11 +163,11 @@ export class SearchDocBox extends React.Component { enter = async (e: React.KeyboardEvent) => { console.log(e.key); if (e.key === "Enter") { - let newdocs= await this.getAllResults(this.query) + 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"` }); - + this.content = Docs.Create.TreeDocument(things, { _width: 200, _height: 400, _chromeStatus: "disabled", title: `Search Docs: "Results"` }); + } } @@ -407,9 +409,9 @@ export class SearchDocBox extends React.Component { return (
- s + Document={this.content} + getTransform={this.props.ScreenToLocalTransform}> + s
{ opacity: 1, transition: "0.4s opacity ease", zIndex: 99, - top:0, + top: 0, }} title={"Add Metadata"} - onClick={action(() => {this.editingMetadata = !this.editingMetadata })} + onClick={action(() => { this.editingMetadata = !this.editingMetadata })} /> -
+
{ // true = checked, false = unchecked @observable private _status: boolean; - @observable private uncheckTimeline: anime.AnimeTimelineInstance; - @observable private checkTimeline: anime.AnimeTimelineInstance; + // @observable private uncheckTimeline: anime.AnimeTimelineInstance; + // @observable private checkTimeline: anime.AnimeTimelineInstance; @observable private checkRef: any; @observable private _resetReaction?: IReactionDisposer; @@ -28,87 +28,87 @@ export class CheckBox extends React.Component{ this._status = this.props.originalStatus; this.checkRef = React.createRef(); - this.checkTimeline = anime.timeline({ - loop: false, - autoplay: false, - direction: "normal", - }); this.uncheckTimeline = anime.timeline({ - loop: false, - autoplay: false, - direction: "normal", - }); + // this.checkTimeline = anime.timeline({ + // loop: false, + // autoplay: false, + // direction: "normal", + // }); this.uncheckTimeline = anime.timeline({ + // loop: false, + // autoplay: false, + // direction: "normal", + // }); } - componentDidMount = () => { - this.uncheckTimeline.add({ - targets: this.checkRef.current, - easing: "easeInOutQuad", - duration: 500, - opacity: 0, - }); - this.checkTimeline.add({ - targets: this.checkRef.current, - easing: "easeInOutQuad", - duration: 500, - strokeDashoffset: [anime.setDashoffset, 0], - opacity: 1 - }); + // componentDidMount = () => { + // this.uncheckTimeline.add({ + // targets: this.checkRef.current, + // easing: "easeInOutQuad", + // duration: 500, + // opacity: 0, + // }); + // this.checkTimeline.add({ + // targets: this.checkRef.current, + // easing: "easeInOutQuad", + // duration: 500, + // strokeDashoffset: [anime.setDashoffset, 0], + // opacity: 1 + // }); - if (this.props.originalStatus) { - this.checkTimeline.play(); - this.checkTimeline.restart(); - } + // if (this.props.originalStatus) { + // this.checkTimeline.play(); + // this.checkTimeline.restart(); + // } - this._resetReaction = reaction( - () => this.props.parent._resetBoolean, - () => { - if (this.props.parent._resetBoolean) { - runInAction(() => { - this.reset(); - this.props.parent._resetCounter++; - if (this.props.parent._resetCounter === this.props.numCount) { - this.props.parent._resetCounter = 0; - this.props.parent._resetBoolean = false; - } - }); - } - }, - ); - } + // this._resetReaction = reaction( + // () => this.props.parent._resetBoolean, + // () => { + // if (this.props.parent._resetBoolean) { + // runInAction(() => { + // this.reset(); + // this.props.parent._resetCounter++; + // if (this.props.parent._resetCounter === this.props.numCount) { + // this.props.parent._resetCounter = 0; + // this.props.parent._resetBoolean = false; + // } + // }); + // } + // }, + // ); + // } - @action.bound - reset() { - if (this.props.default) { - if (!this._status) { - this._status = true; - this.checkTimeline.play(); - this.checkTimeline.restart(); - } - } - else { - if (this._status) { - this._status = false; - this.uncheckTimeline.play(); - this.uncheckTimeline.restart(); - } - } + // @action.bound + // reset() { + // if (this.props.default) { + // if (!this._status) { + // this._status = true; + // this.checkTimeline.play(); + // this.checkTimeline.restart(); + // } + // } + // else { + // if (this._status) { + // this._status = false; + // this.uncheckTimeline.play(); + // this.uncheckTimeline.restart(); + // } + // } - this.props.updateStatus(this.props.default); - } + // this.props.updateStatus(this.props.default); + // } @action.bound onClick = () => { - if (this._status) { - this.uncheckTimeline.play(); - this.uncheckTimeline.restart(); - } - else { - this.checkTimeline.play(); - this.checkTimeline.restart(); + // if (this._status) { + // this.uncheckTimeline.play(); + // this.uncheckTimeline.restart(); + // } + // else { + // this.checkTimeline.play(); + // this.checkTimeline.restart(); - } - this._status = !this._status; - this.props.updateStatus(this._status); + // } + // this._status = !this._status; + // this.props.updateStatus(this._status); } diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 9af8829fa..02b41bc70 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -17,6 +17,7 @@ import "./FilterBox.scss"; import "./SearchBox.scss"; import { SearchItem } from './SearchItem'; import { IconBar } from './IconBar'; +import { FieldFilters } from './FieldFilters'; library.add(faTimes); @@ -338,6 +339,9 @@ export class SearchBox extends React.Component { @computed get resultHeight() { return this._numTotalResults * 70; } + @observable private _filterOpen: boolean = false; + + render() { return (
{ e.stopPropagation(); e.preventDefault(); }}> @@ -353,6 +357,49 @@ export class SearchBox extends React.Component {
+
+
+ + {/* {this.getActiveFilters()} */} +
+
+
+ +
+
+ +
+
+
+
+
+
Required words
+
+
+ +
+
+
+
+
Filter by type of node
+
+
+
+
+
+
Filter by Basic Keys
+
+
+
+
+
+ + +
+
+
{ - const to = params.to || DashSessionAgent.notificationRecipient; - const { error } = await sessionAgent.serverWorker.emit("debug", { to }); - res.send(error ? error.message : `Your request was successful: the server captured and compressed (but did not save) a new back up. It was sent to ${to}.`); - }) - }); + // register({ + // method: Method.GET, + // subscription: this.secureSubscriber("debug", "to?"), + // secureHandler: this.authorizedAction(async ({ req: { params }, res }) => { + // const to = params.to || DashSessionAgent.notificationRecipient; + // const { error } = await sessionAgent.serverWorker.emit("debug", { to }); + // res.send(error ? error.message : `Your request was successful: the server captured and compressed (but did not save) a new back up. It was sent to ${to}.`); + // }) + // }); register({ method: Method.GET, diff --git a/src/server/DashSession/DashSessionAgent.ts b/src/server/DashSession/DashSessionAgent.ts index c55e01243..f22d1cbbc 100644 --- a/src/server/DashSession/DashSessionAgent.ts +++ b/src/server/DashSession/DashSessionAgent.ts @@ -1,223 +1,223 @@ -import { Email, pathFromRoot } from "../ActionUtilities"; -import { red, yellow, green, cyan } from "colors"; -import { get } from "request-promise"; -import { Utils } from "../../Utils"; -import { WebSocket } from "../Websocket/Websocket"; -import { MessageStore } from "../Message"; -import { launchServer, onWindows } from ".."; -import { readdirSync, statSync, createWriteStream, readFileSync, unlinkSync } from "fs"; -import * as Archiver from "archiver"; -import { resolve } from "path"; -import { AppliedSessionAgent, MessageHandler, ExitHandler, Monitor, ServerWorker } from "resilient-server-session"; -import rimraf = require("rimraf"); - -/** - * If we're the monitor (master) thread, we should launch the monitor logic for the session. - * Otherwise, we must be on a worker thread that was spawned *by* the monitor (master) thread, and thus - * our job should be to run the server. - */ -export class DashSessionAgent extends AppliedSessionAgent { - - private readonly signature = "-Dash Server Session Manager"; - private readonly releaseDesktop = pathFromRoot("../../Desktop"); - - /** - * The core method invoked when the single master thread is initialized. - * Installs event hooks, repl commands and additional IPC listeners. - */ - protected async initializeMonitor(monitor: Monitor, sessionKey: string): Promise { - await this.dispatchSessionPassword(sessionKey); - monitor.addReplCommand("pull", [], () => monitor.exec("git pull")); - monitor.addReplCommand("solr", [/start|stop|index/], this.executeSolrCommand); - monitor.addReplCommand("backup", [], this.backup); - monitor.addReplCommand("debug", [/\S+\@\S+/], async ([to]) => this.dispatchZippedDebugBackup(to)); - monitor.on("backup", this.backup); - monitor.on("debug", async ({ to }) => this.dispatchZippedDebugBackup(to)); - monitor.coreHooks.onCrashDetected(this.dispatchCrashReport); - } - - /** - * The core method invoked when a server worker thread is initialized. - * Installs logic to be executed when the server worker dies. - */ - protected async initializeServerWorker(): Promise { - const worker = ServerWorker.Create(launchServer); // server initialization delegated to worker - worker.addExitHandler(this.notifyClient); - return worker; - } - - /** - * Prepares the body of the email with instructions on restoring the transmitted remote database backup locally. - */ - private _remoteDebugInstructions: string | undefined; - private generateDebugInstructions = (zipName: string, target: string): string => { - if (!this._remoteDebugInstructions) { - this._remoteDebugInstructions = readFileSync(resolve(__dirname, "./templates/remote_debug_instructions.txt"), { encoding: "utf8" }); - } - return this._remoteDebugInstructions - .replace(/__zipname__/, zipName) - .replace(/__target__/, target) - .replace(/__signature__/, this.signature); - } - - /** - * Prepares the body of the email with information regarding a crash event. - */ - private _crashInstructions: string | undefined; - private generateCrashInstructions({ name, message, stack }: Error): string { - if (!this._crashInstructions) { - this._crashInstructions = readFileSync(resolve(__dirname, "./templates/crash_instructions.txt"), { encoding: "utf8" }); - } - return this._crashInstructions - .replace(/__name__/, name || "[no error name found]") - .replace(/__message__/, message || "[no error message found]") - .replace(/__stack__/, stack || "[no error stack found]") - .replace(/__signature__/, this.signature); - } - - /** - * This sends a pseudorandomly generated guid to the configuration's recipients, allowing them alone - * to kill the server via the /kill/:key route. - */ - private dispatchSessionPassword = async (sessionKey: string): Promise => { - const { mainLog } = this.sessionMonitor; - const { notificationRecipient } = DashSessionAgent; - mainLog(green("dispatching session key...")); - const error = await Email.dispatch({ - to: notificationRecipient, - subject: "Dash Release Session Admin Authentication Key", - content: [ - `Here's the key for this session (started @ ${new Date().toUTCString()}):`, - sessionKey, - this.signature - ].join("\n\n") - }); - if (error) { - this.sessionMonitor.mainLog(red(`dispatch failure @ ${notificationRecipient} (${yellow(error.message)})`)); - mainLog(red("distribution of session key experienced errors")); - } else { - mainLog(green("successfully distributed session key to recipients")); - } - } - - /** - * This sends an email with the generated crash report. - */ - private dispatchCrashReport: MessageHandler<{ error: Error }> = async ({ error: crashCause }) => { - const { mainLog } = this.sessionMonitor; - const { notificationRecipient } = DashSessionAgent; - const error = await Email.dispatch({ - to: notificationRecipient, - subject: "Dash Web Server Crash", - content: this.generateCrashInstructions(crashCause) - }); - if (error) { - this.sessionMonitor.mainLog(red(`dispatch failure @ ${notificationRecipient} ${yellow(`(${error.message})`)}`)); - mainLog(red("distribution of crash notification experienced errors")); - } else { - mainLog(green("successfully distributed crash notification to recipients")); - } - } - - /** - * Logic for interfacing with Solr. Either starts it, - * stops it, or rebuilds its indicies. - */ - private executeSolrCommand = async (args: string[]): Promise => { - const { exec, mainLog } = this.sessionMonitor; - const action = args[0]; - if (action === "index") { - exec("npx ts-node ./updateSearch.ts", { cwd: pathFromRoot("./src/server") }); - } else { - const command = `${onWindows ? "solr.cmd" : "solr"} ${args[0] === "start" ? "start" : "stop -p 8983"}`; - await exec(command, { cwd: "./solr-8.3.1/bin" }); - try { - await get("http://localhost:8983"); - mainLog(green("successfully connected to 8983 after running solr initialization")); - } catch { - mainLog(red("unable to connect at 8983 after running solr initialization")); - } - } - } - - /** - * Broadcast to all clients that their connection - * is no longer valid, and explain why / what to expect. - */ - private notifyClient: ExitHandler = reason => { - const { _socket } = WebSocket; - if (_socket) { - const message = typeof reason === "boolean" ? (reason ? "exit" : "temporary") : "crash"; - Utils.Emit(_socket, MessageStore.ConnectionTerminated, message); - } - } - - /** - * Performs a backup of the database, saved to the desktop subdirectory. - * This should work as is only on our specific release server. - */ - private backup = async (): Promise => this.sessionMonitor.exec("backup.bat", { cwd: this.releaseDesktop }); - - /** - * Compress either a brand new backup or the most recent backup and send it - * as an attachment to an email, dispatched to the requested recipient. - * @param mode specifies whether or not to make a new backup before exporting - * @param to the recipient of the email - */ - private async dispatchZippedDebugBackup(to: string): Promise { - const { mainLog } = this.sessionMonitor; - try { - // if desired, complete an immediate backup to send - await this.backup(); - mainLog("backup complete"); - - const backupsDirectory = `${this.releaseDesktop}/backups`; - - // sort all backups by their modified time, and choose the most recent one - const target = readdirSync(backupsDirectory).map(filename => ({ - modifiedTime: statSync(`${backupsDirectory}/${filename}`).mtimeMs, - filename - })).sort((a, b) => b.modifiedTime - a.modifiedTime)[0].filename; - mainLog(`targeting ${target}...`); - - // create a zip file and to it, write the contents of the backup directory - const zipName = `${target}.zip`; - const zipPath = `${this.releaseDesktop}/${zipName}`; - const targetPath = `${backupsDirectory}/${target}`; - const output = createWriteStream(zipPath); - const zip = Archiver('zip'); - zip.pipe(output); - zip.directory(`${targetPath}/Dash`, false); - await zip.finalize(); - mainLog(`zip finalized with size ${statSync(zipPath).size} bytes, saved to ${zipPath}`); - - // dispatch the email to the recipient, containing the finalized zip file - const error = await Email.dispatch({ - to, - subject: `Remote debug: compressed backup of ${target}...`, - content: this.generateDebugInstructions(zipName, target), - attachments: [{ filename: zipName, path: zipPath }] - }); - - // since this is intended to be a zero-footprint operation, clean up - // by unlinking both the backup generated earlier in the function and the compressed zip file. - // to generate a persistent backup, just run backup. - unlinkSync(zipPath); - rimraf.sync(targetPath); - - // indicate success or failure - mainLog(`${error === null ? green("successfully dispatched") : red("failed to dispatch")} ${zipName} to ${cyan(to)}`); - error && mainLog(red(error.message)); - } catch (error) { - mainLog(red("unable to dispatch zipped backup...")); - mainLog(red(error.message)); - } - } - -} - -export namespace DashSessionAgent { - - export const notificationRecipient = "brownptcdash@gmail.com"; - -} \ No newline at end of file +// import { Email, pathFromRoot } from "../ActionUtilities"; +// import { red, yellow, green, cyan } from "colors"; +// import { get } from "request-promise"; +// import { Utils } from "../../Utils"; +// import { WebSocket } from "../Websocket/Websocket"; +// import { MessageStore } from "../Message"; +// import { launchServer, onWindows } from ".."; +// import { readdirSync, statSync, createWriteStream, readFileSync, unlinkSync } from "fs"; +// import * as Archiver from "archiver"; +// import { resolve } from "path"; +// import { AppliedSessionAgent, MessageHandler, ExitHandler, Monitor, ServerWorker } from "resilient-server-session"; +// import rimraf = require("rimraf"); + +// /** +// * If we're the monitor (master) thread, we should launch the monitor logic for the session. +// * Otherwise, we must be on a worker thread that was spawned *by* the monitor (master) thread, and thus +// * our job should be to run the server. +// */ +// export class DashSessionAgent extends AppliedSessionAgent { + +// private readonly signature = "-Dash Server Session Manager"; +// private readonly releaseDesktop = pathFromRoot("../../Desktop"); + +// /** +// * The core method invoked when the single master thread is initialized. +// * Installs event hooks, repl commands and additional IPC listeners. +// */ +// protected async initializeMonitor(monitor: Monitor, sessionKey: string): Promise { +// await this.dispatchSessionPassword(sessionKey); +// monitor.addReplCommand("pull", [], () => monitor.exec("git pull")); +// monitor.addReplCommand("solr", [/start|stop|index/], this.executeSolrCommand); +// monitor.addReplCommand("backup", [], this.backup); +// monitor.addReplCommand("debug", [/\S+\@\S+/], async ([to]) => this.dispatchZippedDebugBackup(to)); +// monitor.on("backup", this.backup); +// monitor.on("debug", async ({ to }) => this.dispatchZippedDebugBackup(to)); +// monitor.coreHooks.onCrashDetected(this.dispatchCrashReport); +// } + +// /** +// * The core method invoked when a server worker thread is initialized. +// * Installs logic to be executed when the server worker dies. +// */ +// protected async initializeServerWorker(): Promise { +// const worker = ServerWorker.Create(launchServer); // server initialization delegated to worker +// worker.addExitHandler(this.notifyClient); +// return worker; +// } + +// /** +// * Prepares the body of the email with instructions on restoring the transmitted remote database backup locally. +// */ +// private _remoteDebugInstructions: string | undefined; +// private generateDebugInstructions = (zipName: string, target: string): string => { +// if (!this._remoteDebugInstructions) { +// this._remoteDebugInstructions = readFileSync(resolve(__dirname, "./templates/remote_debug_instructions.txt"), { encoding: "utf8" }); +// } +// return this._remoteDebugInstructions +// .replace(/__zipname__/, zipName) +// .replace(/__target__/, target) +// .replace(/__signature__/, this.signature); +// } + +// /** +// * Prepares the body of the email with information regarding a crash event. +// */ +// private _crashInstructions: string | undefined; +// private generateCrashInstructions({ name, message, stack }: Error): string { +// if (!this._crashInstructions) { +// this._crashInstructions = readFileSync(resolve(__dirname, "./templates/crash_instructions.txt"), { encoding: "utf8" }); +// } +// return this._crashInstructions +// .replace(/__name__/, name || "[no error name found]") +// .replace(/__message__/, message || "[no error message found]") +// .replace(/__stack__/, stack || "[no error stack found]") +// .replace(/__signature__/, this.signature); +// } + +// /** +// * This sends a pseudorandomly generated guid to the configuration's recipients, allowing them alone +// * to kill the server via the /kill/:key route. +// */ +// private dispatchSessionPassword = async (sessionKey: string): Promise => { +// const { mainLog } = this.sessionMonitor; +// const { notificationRecipient } = DashSessionAgent; +// mainLog(green("dispatching session key...")); +// const error = await Email.dispatch({ +// to: notificationRecipient, +// subject: "Dash Release Session Admin Authentication Key", +// content: [ +// `Here's the key for this session (started @ ${new Date().toUTCString()}):`, +// sessionKey, +// this.signature +// ].join("\n\n") +// }); +// if (error) { +// this.sessionMonitor.mainLog(red(`dispatch failure @ ${notificationRecipient} (${yellow(error.message)})`)); +// mainLog(red("distribution of session key experienced errors")); +// } else { +// mainLog(green("successfully distributed session key to recipients")); +// } +// } + +// /** +// * This sends an email with the generated crash report. +// */ +// private dispatchCrashReport: MessageHandler<{ error: Error }> = async ({ error: crashCause }) => { +// const { mainLog } = this.sessionMonitor; +// const { notificationRecipient } = DashSessionAgent; +// const error = await Email.dispatch({ +// to: notificationRecipient, +// subject: "Dash Web Server Crash", +// content: this.generateCrashInstructions(crashCause) +// }); +// if (error) { +// this.sessionMonitor.mainLog(red(`dispatch failure @ ${notificationRecipient} ${yellow(`(${error.message})`)}`)); +// mainLog(red("distribution of crash notification experienced errors")); +// } else { +// mainLog(green("successfully distributed crash notification to recipients")); +// } +// } + +// /** +// * Logic for interfacing with Solr. Either starts it, +// * stops it, or rebuilds its indicies. +// */ +// private executeSolrCommand = async (args: string[]): Promise => { +// const { exec, mainLog } = this.sessionMonitor; +// const action = args[0]; +// if (action === "index") { +// exec("npx ts-node ./updateSearch.ts", { cwd: pathFromRoot("./src/server") }); +// } else { +// const command = `${onWindows ? "solr.cmd" : "solr"} ${args[0] === "start" ? "start" : "stop -p 8983"}`; +// await exec(command, { cwd: "./solr-8.3.1/bin" }); +// try { +// await get("http://localhost:8983"); +// mainLog(green("successfully connected to 8983 after running solr initialization")); +// } catch { +// mainLog(red("unable to connect at 8983 after running solr initialization")); +// } +// } +// } + +// /** +// * Broadcast to all clients that their connection +// * is no longer valid, and explain why / what to expect. +// */ +// private notifyClient: ExitHandler = reason => { +// const { _socket } = WebSocket; +// if (_socket) { +// const message = typeof reason === "boolean" ? (reason ? "exit" : "temporary") : "crash"; +// Utils.Emit(_socket, MessageStore.ConnectionTerminated, message); +// } +// } + +// /** +// * Performs a backup of the database, saved to the desktop subdirectory. +// * This should work as is only on our specific release server. +// */ +// private backup = async (): Promise => this.sessionMonitor.exec("backup.bat", { cwd: this.releaseDesktop }); + +// /** +// * Compress either a brand new backup or the most recent backup and send it +// * as an attachment to an email, dispatched to the requested recipient. +// * @param mode specifies whether or not to make a new backup before exporting +// * @param to the recipient of the email +// */ +// private async dispatchZippedDebugBackup(to: string): Promise { +// const { mainLog } = this.sessionMonitor; +// try { +// // if desired, complete an immediate backup to send +// await this.backup(); +// mainLog("backup complete"); + +// const backupsDirectory = `${this.releaseDesktop}/backups`; + +// // sort all backups by their modified time, and choose the most recent one +// const target = readdirSync(backupsDirectory).map(filename => ({ +// modifiedTime: statSync(`${backupsDirectory}/${filename}`).mtimeMs, +// filename +// })).sort((a, b) => b.modifiedTime - a.modifiedTime)[0].filename; +// mainLog(`targeting ${target}...`); + +// // create a zip file and to it, write the contents of the backup directory +// const zipName = `${target}.zip`; +// const zipPath = `${this.releaseDesktop}/${zipName}`; +// const targetPath = `${backupsDirectory}/${target}`; +// const output = createWriteStream(zipPath); +// const zip = Archiver('zip'); +// zip.pipe(output); +// zip.directory(`${targetPath}/Dash`, false); +// await zip.finalize(); +// mainLog(`zip finalized with size ${statSync(zipPath).size} bytes, saved to ${zipPath}`); + +// // dispatch the email to the recipient, containing the finalized zip file +// const error = await Email.dispatch({ +// to, +// subject: `Remote debug: compressed backup of ${target}...`, +// content: this.generateDebugInstructions(zipName, target), +// attachments: [{ filename: zipName, path: zipPath }] +// }); + +// // since this is intended to be a zero-footprint operation, clean up +// // by unlinking both the backup generated earlier in the function and the compressed zip file. +// // to generate a persistent backup, just run backup. +// unlinkSync(zipPath); +// rimraf.sync(targetPath); + +// // indicate success or failure +// mainLog(`${error === null ? green("successfully dispatched") : red("failed to dispatch")} ${zipName} to ${cyan(to)}`); +// error && mainLog(red(error.message)); +// } catch (error) { +// mainLog(red("unable to dispatch zipped backup...")); +// mainLog(red(error.message)); +// } +// } + +// } + +// export namespace DashSessionAgent { + +// export const notificationRecipient = "brownptcdash@gmail.com"; + +// } \ No newline at end of file diff --git a/src/server/index.ts b/src/server/index.ts index 313a2f0e2..454d99305 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -22,7 +22,7 @@ import GeneralGoogleManager from "./ApiManagers/GeneralGoogleManager"; import GooglePhotosManager from "./ApiManagers/GooglePhotosManager"; import { Logger } from "./ProcessFactory"; import { yellow } from "colors"; -import { DashSessionAgent } from "./DashSession/DashSessionAgent"; +// import { DashSessionAgent } from "./DashSession/DashSessionAgent"; import SessionManager from "./ApiManagers/SessionManager"; import { AppliedSessionAgent } from "resilient-server-session"; @@ -141,7 +141,7 @@ export async function launchServer() { * So, the 'else' clause is exactly what we've always run when executing npm start. */ if (process.env.RELEASE) { - (sessionAgent = new DashSessionAgent()).launch(); + // (sessionAgent = new DashSessionAgent()).launch(); } else { launchServer(); } -- cgit v1.2.3-70-g09d2 From 60a35a83b1e07426092df6261be1a2c41bc74bbd Mon Sep 17 00:00:00 2001 From: vellichora Date: Sun, 1 Mar 2020 17:20:45 -0500 Subject: ui etc --- src/client/documents/Documents.ts | 5 +- src/client/views/nodes/DocumentContentsView.tsx | 4 +- src/client/views/nodes/QueryBox.tsx | 8 +- src/client/views/search/FilterBox.scss | 9 +- src/client/views/search/SearchBox.scss | 186 +++++++++++++++++++++++- src/client/views/search/SearchBox.tsx | 77 +++++----- 6 files changed, 236 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 8ade14251..96830d8dc 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -44,8 +44,7 @@ import { ComputedField, ScriptField } from "../../new_fields/ScriptField"; import { ProxyField } from "../../new_fields/Proxy"; import { DocumentType } from "./DocumentTypes"; import { RecommendationsBox } from "../views/RecommendationsBox"; -import { SearchDocBox } from "../views/SearchDocBox"; - +import { SearchBox } from "../views/search/SearchBox"; //import { PresBox } from "../views/nodes/PresBox"; //import { PresField } from "../../new_fields/PresField"; @@ -262,7 +261,7 @@ export namespace Docs { options: { backgroundColor: "transparent" } }], [DocumentType.SEARCHBOX, { - layout: { view: SearchDocBox }, + layout: { view: SearchBox }, options: { width: 200, height: 200 }, }] ]); diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 15dd1b29f..3ef8126bc 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -34,7 +34,7 @@ import { WebBox } from "./WebBox"; import { InkingStroke } from "../InkingStroke"; import React = require("react"); import { RecommendationsBox } from "../RecommendationsBox"; -import { SearchDocBox } from "../SearchDocBox"; +import { SearchBox } from "../search/SearchBox"; import { TraceMobx } from "../../../new_fields/util"; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? @@ -105,7 +105,7 @@ export class DocumentContentsView extends React.Component { render() { return
- -
; +
+ +
+ +
; } } \ No newline at end of file diff --git a/src/client/views/search/FilterBox.scss b/src/client/views/search/FilterBox.scss index ebb39460d..094ea9cc5 100644 --- a/src/client/views/search/FilterBox.scss +++ b/src/client/views/search/FilterBox.scss @@ -4,7 +4,6 @@ .filter-form { padding: 25px; width: 440px; - background: whitesmoke; position: relative; right: 1px; color: grey; @@ -12,9 +11,7 @@ display: inline-block; transform-origin: top; overflow: auto; - border-radius: 15px; - box-shadow: $intermediate-color 0.2vw 0.2vw 0.4vw; - border: solid #BBBBBBBB 1px; + border-bottom: solid black 3px; .top-filter-header { @@ -124,7 +121,7 @@ max-width: 40px; flex: initial; - &.icon{ + &.icon { width: 40px; text-align: center; margin-bottom: 5px; @@ -150,7 +147,7 @@ transition: all 0.2s ease-in-out; } - &.icon:hover + .description { + &.icon:hover+.description { opacity: 1; } } diff --git a/src/client/views/search/SearchBox.scss b/src/client/views/search/SearchBox.scss index 11714748a..70b9ef75e 100644 --- a/src/client/views/search/SearchBox.scss +++ b/src/client/views/search/SearchBox.scss @@ -4,13 +4,14 @@ .searchBox-container { display: flex; flex-direction: column; - width:100%; - height:100%; + width: 100%; + height: 100%; position: absolute; font-size: 10px; line-height: 1; overflow: hidden; } + .searchBox-bar { height: 32px; display: flex; @@ -19,7 +20,7 @@ padding-left: 2px; padding-right: 2px; -.searchBox-barChild { + .searchBox-barChild { &.searchBox-collection { flex: 0 1 auto; @@ -65,7 +66,7 @@ } .searchBox-results { - display:flex; + display: flex; flex-direction: column; top: 300px; display: flex; @@ -83,6 +84,181 @@ text-transform: uppercase; text-align: left; font-weight: bold; - margin-left: 28px; + } +} + +.filter-form { + padding: 25px; + width: 440px; + position: relative; + right: 1px; + color: grey; + flex-direction: column; + display: inline-block; + transform-origin: top; + overflow: auto; + border-bottom: solid black 3px; + + .top-filter-header { + + #header { + text-transform: uppercase; + letter-spacing: 2px; + font-size: 13; + width: 80%; + } + + .close-icon { + width: 20%; + opacity: .6; + position: relative; + display: block; + + .line { + display: block; + background: $alt-accent; + width: 20; + height: 3; + position: absolute; + right: 0; + border-radius: ($height-line / 2); + + &.line-1 { + transform: rotate(45deg); + top: 45%; + } + + &.line-2 { + transform: rotate(-45deg); + top: 45%; + } + } + } + + .close-icon:hover { + opacity: 1; + } + + } + + .filter-options { + + .filter-div { + margin-top: 10px; + margin-bottom: 10px; + display: inline-block; + width: 100%; + border-color: rgba(178, 206, 248, .2); // $darker-alt-accent + border-top-style: solid; + + .filter-header { + display: flex; + align-items: center; + margin-bottom: 10px; + letter-spacing: 2px; + + .filter-title { + font-size: 13; + text-transform: uppercase; + margin-top: 10px; + margin-bottom: 10px; + -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; + } + } + + .filter-header:hover .filter-title { + transform: scale(1.05); + } + + .filter-panel { + max-height: 0px; + width: 100%; + overflow: hidden; + opacity: 0; + transform-origin: top; + -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; + text-align: center; + } + } + } + + .filter-buttons { + border-color: rgba(178, 206, 248, .2); // $darker-alt-accent + 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; + + .save-filter, + .reset-filter, + .all-filter { + background-color: gray; + } + + .save-filter:hover, + .reset-filter:hover, + .all-filter:hover { + background-color: $darker-alt-accent; + } } } \ No newline at end of file diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 02b41bc70..5e40b2c8b 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -12,12 +12,13 @@ import { Utils } from '../../../Utils'; import { Docs } from '../../documents/Documents'; import { SetupDrag } from '../../util/DragManager'; import { SearchUtil } from '../../util/SearchUtil'; -import { FilterBox } from './FilterBox'; -import "./FilterBox.scss"; +// import { FilterBox } from './FilterBox'; +// import "./FilterBox.scss"; import "./SearchBox.scss"; import { SearchItem } from './SearchItem'; import { IconBar } from './IconBar'; import { FieldFilters } from './FieldFilters'; +import { FieldView } from '../nodes/FieldView'; library.add(faTimes); @@ -43,6 +44,7 @@ export class SearchBox extends React.Component { private _maxSearchIndex: number = 0; private _curRequest?: Promise = undefined; + public static LayoutString(fieldKey: string) { return FieldView.LayoutString(SearchBox, fieldKey); } constructor(props: any) { super(props); @@ -110,12 +112,12 @@ export class SearchBox extends React.Component { @action submitSearch = async () => { let query = this._searchString; - query = FilterBox.Instance.getFinalQuery(query); + // query = FilterBox.Instance.getFinalQuery(query); this._results = []; this._resultsSet.clear(); this._isSearch = []; this._visibleElements = []; - FilterBox.Instance.closeFilter(); + // FilterBox.Instance.closeFilter(); //if there is no query there should be no result if (query === "") { @@ -137,15 +139,17 @@ export class SearchBox extends React.Component { } getAllResults = async (query: string) => { - return SearchUtil.Search(query, true, { fq: this.filterQuery, start: 0, rows: 10000000 }); - } + return SearchUtil.Search(query, true, { 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(" ")})` : ""); + //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; @@ -155,7 +159,8 @@ 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: this.NumResults, 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) => { + this._curRequest = SearchUtil.Search(query, true, { 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) { @@ -169,7 +174,8 @@ 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]); - const filteredDocs = FilterBox.Instance.filterDocsByType(docs); + //const filteredDocs = FilterBox.Instance.filterDocsByType(docs); + const filteredDocs = docs; runInAction(() => { // this._results.push(...filteredDocs); filteredDocs.forEach(doc => { @@ -201,8 +207,11 @@ export class SearchBox extends React.Component { collectionRef = React.createRef(); startDragCollection = async () => { - const res = await this.getAllResults(FilterBox.Instance.getFinalQuery(this._searchString)); - const filtered = FilterBox.Instance.filterDocsByType(res.docs); + //const res = await this.getAllResults(FilterBox.Instance.getFinalQuery(this._searchString)); + const res = await this.getAllResults(this._searchString); + + //const filtered = FilterBox.Instance.filterDocsByType(res.docs); + const filtered = res.docs; // console.log(this._results) const docs = filtered.map(doc => { const isProto = Doc.GetT(doc, "isPrototype", "boolean", true); @@ -236,22 +245,24 @@ export class SearchBox extends React.Component { } } //return Docs.Create.TreeDocument(docs, { _width: 200, _height: 400, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` }); - return Docs.Create.SearchDocument(docs, { _width: 200, _height: 400, searchText: this._searchString, title: `Search Docs: "${this._searchString}"` }); + //return Docs.Create.SearchDocument(docs, { _width: 200, _height: 400, searchText: this._searchString, title: `Search Docs: "${this._searchString}"` }); + return Docs.Create.QueryDocument({ + }); } @action.bound openSearch(e: React.SyntheticEvent) { e.stopPropagation(); this._openNoResults = false; - FilterBox.Instance.closeFilter(); + //FilterBox.Instance.closeFilter(); this._resultsOpen = true; this._searchbarOpen = true; - FilterBox.Instance._pointerTime = e.timeStamp; + //FilterBox.Instance._pointerTime = e.timeStamp; } @action.bound closeSearch = () => { - FilterBox.Instance.closeFilter(); + //FilterBox.Instance.closeFilter(); this.closeResults(); this._searchbarOpen = false; } @@ -352,17 +363,11 @@ export class SearchBox extends React.Component { - -
-
-
+
-
-
- - {/* {this.getActiveFilters()} */} -
-
+ +
+
@@ -383,20 +388,22 @@ export class SearchBox extends React.Component {
Filter by type of node
-
+
Filter by Basic Keys
-
+ {/*
+ updateAuthorStatus={this.updateAuthorStatus} updateDataStatus={this.updateDataStatus} updateTitleStatus={this.updateTitleStatus} />
*/} +
+
+
+ +
-
-
- -
-- cgit v1.2.3-70-g09d2 From 0777ad8db317999a4a878a4ab91ff706426303b7 Mon Sep 17 00:00:00 2001 From: vellichora Date: Sat, 7 Mar 2020 15:27:49 -0500 Subject: search ui changes --- src/client/views/search/IconBar.scss | 4 +- src/client/views/search/IconBar.tsx | 20 ++- src/client/views/search/IconButton.scss | 1 - src/client/views/search/IconButton.tsx | 9 +- src/client/views/search/SearchBox.scss | 208 ++++++++++++++++++-------------- src/client/views/search/SearchBox.tsx | 61 +++++++--- 6 files changed, 180 insertions(+), 123 deletions(-) (limited to 'src') diff --git a/src/client/views/search/IconBar.scss b/src/client/views/search/IconBar.scss index 2555ad271..c6dc2a6cd 100644 --- a/src/client/views/search/IconBar.scss +++ b/src/client/views/search/IconBar.scss @@ -3,9 +3,7 @@ .icon-bar { display: flex; justify-content: space-evenly; - align-items: center; height: 35px; width: 100%; - flex-wrap: wrap; - margin-bottom: 10px; + flex-direction: row-reverse; } \ No newline at end of file diff --git a/src/client/views/search/IconBar.tsx b/src/client/views/search/IconBar.tsx index cff397407..fe7dd4223 100644 --- a/src/client/views/search/IconBar.tsx +++ b/src/client/views/search/IconBar.tsx @@ -9,7 +9,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { library } from '@fortawesome/fontawesome-svg-core'; import * as _ from "lodash"; import { IconButton } from './IconButton'; -import { FilterBox } from './FilterBox'; +import { DocumentType } from "../../documents/DocumentTypes"; + library.add(faSearch); library.add(faObjectGroup); @@ -25,6 +26,9 @@ library.add(faBan); @observer export class IconBar extends React.Component { + public _allIcons: string[] = [DocumentType.AUDIO, DocumentType.COL, DocumentType.IMG, DocumentType.LINK, DocumentType.PDF, DocumentType.TEXT, DocumentType.VID, DocumentType.WEB, DocumentType.TEMPLATE]; + + @observable private _icons: string[] = this._allIcons; static Instance: IconBar; @@ -33,16 +37,22 @@ export class IconBar extends React.Component { @observable public _reset: number = 0; @observable public _select: number = 0; + @action.bound + updateIcon(newArray: string[]) { this._icons = newArray; } + + @action.bound + getIcons(): string[] { return this._icons; } + constructor(props: any) { super(props); IconBar.Instance = this; } @action.bound - getList(): string[] { return FilterBox.Instance.getIcons(); } + getList(): string[] { return this.getIcons(); } @action.bound - updateList(newList: string[]) { FilterBox.Instance.updateIcon(newList); } + updateList(newList: string[]) { this.updateIcon(newList); } @action.bound resetSelf = () => { @@ -53,13 +63,13 @@ export class IconBar extends React.Component { @action.bound selectAll = () => { this._selectAllClicked = true; - this.updateList(FilterBox.Instance._allIcons); + this.updateList(this._allIcons); } render() { return (
- {FilterBox.Instance._allIcons.map((type: string) => + {this._allIcons.map((type: string) => )}
diff --git a/src/client/views/search/IconButton.scss b/src/client/views/search/IconButton.scss index 4a3107676..4ec03c7c9 100644 --- a/src/client/views/search/IconButton.scss +++ b/src/client/views/search/IconButton.scss @@ -5,7 +5,6 @@ flex-direction: column; align-items: center; width: 30px; - height: 60px; .type-icon { height: 30px; diff --git a/src/client/views/search/IconButton.tsx b/src/client/views/search/IconButton.tsx index f01508141..bea8cc0a7 100644 --- a/src/client/views/search/IconButton.tsx +++ b/src/client/views/search/IconButton.tsx @@ -11,7 +11,6 @@ import '../globalCssVariables.scss'; import * as _ from "lodash"; import { IconBar } from './IconBar'; import { props } from 'bluebird'; -import { FilterBox } from './FilterBox'; import { Search } from '../../../server/Search'; import { gravity } from 'sharp'; @@ -34,7 +33,7 @@ interface IconButtonProps { @observer export class IconButton extends React.Component{ - @observable private _isSelected: boolean = FilterBox.Instance.getIcons().indexOf(this.props.type) !== -1; + @observable private _isSelected: boolean = IconBar.Instance.getIcons().indexOf(this.props.type) !== -1; @observable private _hover = false; private _resetReaction?: IReactionDisposer; private _selectAllReaction?: IReactionDisposer; @@ -108,7 +107,7 @@ export class IconButton extends React.Component{ @action.bound onClick = () => { - const newList: string[] = FilterBox.Instance.getIcons(); + const newList: string[] = IconBar.Instance.getIcons(); if (!this._isSelected) { this._isSelected = true; @@ -119,7 +118,7 @@ export class IconButton extends React.Component{ _.pull(newList, this.props.type); } - FilterBox.Instance.updateIcon(newList); + IconBar.Instance.updateIcon(newList); } selected = { @@ -186,7 +185,7 @@ export class IconButton extends React.Component{ > {this.getFA()}
-
{this.props.type}
+ {/*
{this.props.type}
*/}
); } diff --git a/src/client/views/search/SearchBox.scss b/src/client/views/search/SearchBox.scss index 70b9ef75e..11f5e4d91 100644 --- a/src/client/views/search/SearchBox.scss +++ b/src/client/views/search/SearchBox.scss @@ -88,113 +88,139 @@ } .filter-form { - padding: 25px; - width: 440px; position: relative; right: 1px; color: grey; flex-direction: column; - display: inline-block; transform-origin: top; - overflow: auto; - border-bottom: solid black 3px; + border-bottom: solid grey 1px; + margin: 5px; - .top-filter-header { + .filter-header { + display: flex; + position: relative; + right: 1px; + color: grey; + flex-direction: row-reverse; + transform-origin: top; + justify-content: space-evenly; + margin-bottom: 5px; - #header { - text-transform: uppercase; - letter-spacing: 2px; - font-size: 13; - width: 80%; - } - .close-icon { - width: 20%; - opacity: .6; + .filter-item { position: relative; - display: block; - - .line { - display: block; - background: $alt-accent; - width: 20; - height: 3; - position: absolute; - right: 0; - border-radius: ($height-line / 2); - - &.line-1 { - transform: rotate(45deg); - top: 45%; - } - - &.line-2 { - transform: rotate(-45deg); - top: 45%; - } - } - } - - .close-icon:hover { - opacity: 1; - } - - } - .filter-options { - - .filter-div { - margin-top: 10px; - margin-bottom: 10px; - display: inline-block; - width: 100%; - border-color: rgba(178, 206, 248, .2); // $darker-alt-accent - border-top-style: solid; - - .filter-header { - display: flex; - align-items: center; - margin-bottom: 10px; - letter-spacing: 2px; - - .filter-title { - font-size: 13; - text-transform: uppercase; - margin-top: 10px; - margin-bottom: 10px; - -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; - } - } - - .filter-header:hover .filter-title { - transform: scale(1.05); - } - - .filter-panel { - max-height: 0px; - width: 100%; - overflow: hidden; - opacity: 0; - transform-origin: top; - -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; - text-align: center; - } } } - .filter-buttons { - border-color: rgba(178, 206, 248, .2); // $darker-alt-accent - border-top-style: solid; - padding-top: 10px; + .filter-body { + position: relative; + right: 1px; + color: grey; + transform-origin: top; + border-top: grey 1px solid; + padding-top: 5px; + margin-left: 10px; + margin-right: 10px; } } +// .top-filter-header { + +// #header { +// text-transform: uppercase; +// letter-spacing: 2px; +// font-size: 13; +// width: 80%; +// } + +// .close-icon { +// width: 20%; +// opacity: .6; +// position: relative; +// display: block; + +// .line { +// display: block; +// background: $alt-accent; +// width: 20; +// height: 3; +// position: absolute; +// right: 0; +// border-radius: ($height-line / 2); + +// &.line-1 { +// transform: rotate(45deg); +// top: 45%; +// } + +// &.line-2 { +// transform: rotate(-45deg); +// top: 45%; +// } +// } +// } + +// .close-icon:hover { +// opacity: 1; +// } + +// } + +// .filter-options { + +// .filter-div { +// margin-top: 10px; +// margin-bottom: 10px; +// display: inline-block; +// width: 100%; +// border-color: rgba(178, 206, 248, .2); // $darker-alt-accent +// border-top-style: solid; + +// .filter-header { +// display: flex; +// align-items: center; +// margin-bottom: 10px; +// letter-spacing: 2px; + +// .filter-title { +// font-size: 13; +// text-transform: uppercase; +// margin-top: 10px; +// margin-bottom: 10px; +// -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; +// } +// } + +// .filter-header:hover .filter-title { +// transform: scale(1.05); +// } + +// .filter-panel { +// max-height: 0px; +// width: 100%; +// overflow: hidden; +// opacity: 0; +// transform-origin: top; +// -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; +// text-align: center; +// } +// } +// } + +// .filter-buttons { +// border-color: rgba(178, 206, 248, .2); // $darker-alt-accent +// border-top-style: solid; +// padding-top: 10px; +// } + + .active-filters { display: flex; flex-direction: row-reverse; diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 5e40b2c8b..1025629d5 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -46,6 +46,14 @@ export class SearchBox extends React.Component { private _curRequest?: Promise = undefined; public static LayoutString(fieldKey: string) { return FieldView.LayoutString(SearchBox, fieldKey); } + + //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 = false; + @observable private _nodeStatus: boolean = false; + @observable private _keyStatus: boolean = false; + + constructor(props: any) { super(props); @@ -352,6 +360,22 @@ export class SearchBox extends React.Component { @observable private _filterOpen: boolean = false; + //if true, any keywords can be used. if false, all keywords are required. + @action.bound + handleWordQueryChange = () => { + this._basicWordStatus = !this._basicWordStatus; + } + + @action.bound + handleNodeChange = () => { + this._nodeStatus = !this._nodeStatus; + } + + @action.bound + handleKeyChange = () => { + this._keyStatus = !this._keyStatus; + } + render() { return ( @@ -366,16 +390,22 @@ export class SearchBox extends React.Component {
-
-
-
- -
-
- -
-
-
+
+
+ + + +
+
+ + +
+
+ +
+ + + {/*
Required words
@@ -395,17 +425,12 @@ export class SearchBox extends React.Component {
Filter by Basic Keys
- {/*
*/} + updateAuthorStatus={this.updateAuthorStatus} updateDataStatus={this.updateDataStatus} updateTitleStatus={this.updateTitleStatus} />
-
- - -
-
-
+
*/}
Date: Wed, 11 Mar 2020 15:53:41 -0400 Subject: more css --- src/client/views/search/FilterBox.tsx | 2 +- src/client/views/search/SearchBox.scss | 11 +++++------ src/client/views/search/SearchBox.tsx | 9 ++++----- 3 files changed, 10 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/client/views/search/FilterBox.tsx b/src/client/views/search/FilterBox.tsx index 684f50766..432e18b22 100644 --- a/src/client/views/search/FilterBox.tsx +++ b/src/client/views/search/FilterBox.tsx @@ -387,7 +387,7 @@ export class FilterBox extends React.Component { {/* {this.getActiveFilters()} */}
{this._filterOpen ? ( -
+
diff --git a/src/client/views/search/SearchBox.scss b/src/client/views/search/SearchBox.scss index 11f5e4d91..176ed646d 100644 --- a/src/client/views/search/SearchBox.scss +++ b/src/client/views/search/SearchBox.scss @@ -10,6 +10,7 @@ font-size: 10px; line-height: 1; overflow: hidden; + background: lightgrey, } .searchBox-bar { @@ -18,7 +19,6 @@ justify-content: flex-end; align-items: center; padding-left: 2px; - padding-right: 2px; .searchBox-barChild { @@ -34,8 +34,7 @@ -webkit-transition: width 0.4s; transition: width 0.4s; align-self: stretch; - margin-left: 2px; - margin-right: 2px + } .searchBox-input:focus { @@ -89,12 +88,12 @@ .filter-form { position: relative; - right: 1px; - color: grey; + background: black; flex-direction: column; transform-origin: top; border-bottom: solid grey 1px; - margin: 5px; + padding: 5px; + transition: height 0.5s ease, display 0.5s ease; .filter-header { display: flex; diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 1025629d5..4f0ca5709 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -391,14 +391,13 @@ export class SearchBox extends React.Component {
-
- - - +
+ + +
-
-- cgit v1.2.3-70-g09d2 From 13e6b075154001ce33845a72454e3cd039a92670 Mon Sep 17 00:00:00 2001 From: Andy Rickert Date: Tue, 24 Mar 2020 19:03:19 -0700 Subject: reaally pretty drop down menu functionality : ) --- src/client/views/SearchDocBox.tsx | 2 +- src/client/views/search/IconBar.scss | 3 +- src/client/views/search/SearchBox.scss | 14 ++++- src/client/views/search/SearchBox.tsx | 109 +++++++++++++++++++++++++++++++-- 4 files changed, 118 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/client/views/SearchDocBox.tsx b/src/client/views/SearchDocBox.tsx index 5a76a882f..c57f9e737 100644 --- a/src/client/views/SearchDocBox.tsx +++ b/src/client/views/SearchDocBox.tsx @@ -411,7 +411,7 @@ export class SearchDocBox extends React.Component { - s +
document.getElementById("node")?.scrollHeight,()=>{console.log("longer")}) + } + private _reactionDisposer?: IReactionDisposer; + componentDidMount = () => { if (this.inputRef.current) { this.inputRef.current.focus(); runInAction(() => { this._searchbarOpen = true; }); + } } + @action getViews = async (doc: Doc) => { const results = await SearchUtil.GetViewsOfDocument(doc); @@ -369,6 +375,12 @@ export class SearchBox extends React.Component { @action.bound handleNodeChange = () => { this._nodeStatus = !this._nodeStatus; + if (this._nodeStatus){ + this.expandSection("node") + } + else{ + this.collapseSection("node") + } } @action.bound @@ -376,8 +388,95 @@ export class SearchBox extends React.Component { this._keyStatus = !this._keyStatus; } + @action.bound + handleFilterChange=() =>{ + this._filterOpen=!this._filterOpen; + if (this._filterOpen){ + this.expandSection("filterhead"); + document.getElementById("filterhead")!.style.padding="5"; + } + else{ + this.collapseSection("filterhead"); + + + } + } + // @observable + // private menuHeight= 0; + + @computed + get menuHeight(){ + return document.getElementById("hi")?.clientHeight; + } + + + collapseSection(thing:string) { + let element= document.getElementById(thing)!; + // get the height of the element's inner content, regardless of its actual size + var sectionHeight = element.scrollHeight; + + // temporarily disable all css transitions + var elementTransition = element.style.transition; + element.style.transition = ''; + + // on the next frame (as soon as the previous style change has taken effect), + // explicitly set the element's height to its current pixel height, so we + // aren't transitioning out of 'auto' + requestAnimationFrame(function() { + element.style.height = sectionHeight + 'px'; + element.style.transition = elementTransition; + + // on the next frame (as soon as the previous style change has taken effect), + // have the element transition to height: 0 + requestAnimationFrame(function() { + element.style.height = 0 + 'px'; + thing == "filterhead"? document.getElementById("filterhead")!.style.padding="0" : null; + }); + }); + + // mark the section as "currently collapsed" + element.setAttribute('data-collapsed', 'true'); + } + + expandSection(thing:string) { + console.log("expand"); + let element= document.getElementById(thing)!; + // get the height of the element's inner content, regardless of its actual size + var sectionHeight = element.scrollHeight; + + // have the element transition to the height of its inner content + let temp = element.style.height; + element.style.height = sectionHeight + 'px'; + + // when the next css transition finishes (which should be the one we just triggered) + element.addEventListener('transitionend', function handler(e) { + // remove this event listener so it only gets triggered once + console.log("autoset"); + element.removeEventListener('transitionend', handler); + + // remove "height" from the element's inline styles, so it can return to its initial value + element.style.height="auto"; + //element.style.height = undefined; + }); + + // mark the section as "currently not collapsed" + element.setAttribute('data-collapsed', 'false'); + + } + + autoset(thing: string){ + let element= document.getElementById(thing)!; + console.log("autoset"); + element.removeEventListener('transitionend', function(e){}); + + // remove "height" from the element's inline styles, so it can return to its initial value + element.style.height="auto"; + //element.style.height = undefined; + + } render() { + return (
{ e.stopPropagation(); e.preventDefault(); }}>
@@ -387,16 +486,16 @@ export class SearchBox extends React.Component { - +
-
-
+
+
-
+
-- cgit v1.2.3-70-g09d2 From b33ba2eb7a4bb6744f07c3ee8d86c55ec7b599b5 Mon Sep 17 00:00:00 2001 From: Andy Rickert Date: Tue, 31 Mar 2020 16:15:10 -0700 Subject: more settings ui + huge bugfixes with document dragging and selection --- src/client/documents/Documents.ts | 2 +- src/client/util/DragManager.ts | 1 + src/client/util/SelectionManager.ts | 1 + src/client/views/nodes/DocumentView.tsx | 15 ++++++ src/client/views/nodes/QueryBox.tsx | 61 +++++++++++++++++++--- src/client/views/search/IconButton.tsx | 7 ++- src/client/views/search/SearchBox.scss | 8 ++- src/client/views/search/SearchBox.tsx | 28 +++++----- .../authentication/models/current_user_utils.ts | 2 +- 9 files changed, 101 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 96830d8dc..247f7fa3e 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -261,7 +261,7 @@ export namespace Docs { options: { backgroundColor: "transparent" } }], [DocumentType.SEARCHBOX, { - layout: { view: SearchBox }, + layout: { view: SearchBox, dataField:data}, options: { width: 200, height: 200 }, }] ]); diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 5d2f1bc06..deb2da939 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -267,6 +267,7 @@ export namespace DragManager { } function StartDrag(eles: HTMLElement[], dragData: { [id: string]: any }, downX: number, downY: number, options?: DragOptions, finishDrag?: (dropData: DragCompleteEvent) => void) { + console.log("drag"); eles = eles.filter(e => e); if (!dragDiv) { dragDiv = document.createElement("div"); diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 4fd8abb12..89b900115 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -16,6 +16,7 @@ export namespace SelectionManager { @action SelectDoc(docView: DocumentView, ctrlPressed: boolean): void { + console.log("select"); // if doc is not in SelectedDocuments, add it if (!manager.SelectedDocuments.get(docView)) { if (!ctrlPressed) { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index aa07db2a0..c359be090 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -277,8 +277,16 @@ export class DocumentView extends DocComponent(Docu } onClick = async (e: React.MouseEvent | React.PointerEvent) => { + console.log(this.props.Document[Id]) + console.log(e.nativeEvent.cancelBubble); + console.log(CurrentUserUtils.MainDocId !== this.props.Document[Id]); + console.log(Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD); + console.log(Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD); + if (!e.nativeEvent.cancelBubble && !this.Document.ignoreClick && CurrentUserUtils.MainDocId !== this.props.Document[Id] && (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) { + console.log("click"); + e.stopPropagation(); let preventDefault = true; if (this._doubleTap && this.props.renderDepth && !this.onClickHandler?.script) { // disable double-click to show full screen for things that have an on click behavior since clicking them twice can be misinterpreted as a double click @@ -292,11 +300,17 @@ export class DocumentView extends DocComponent(Docu } else if (this.onClickHandler && this.onClickHandler.script) { this.onClickHandler.script.run({ this: this.Document.isTemplateForField && this.props.DataDoc ? this.props.DataDoc : this.props.Document, containingCollection: this.props.ContainingCollectionDoc }, console.log); } else if (this.Document.type === DocumentType.BUTTON) { + console.log("button"); + ScriptBox.EditButtonScript("On Button Clicked ...", this.props.Document, "onClick", e.clientX, e.clientY); } else if (this.props.Document.isButton === "Selector") { // this should be moved to an OnClick script FormattedTextBoxComment.Hide(); + console.log("button2"); + this.Document.links?.[0] instanceof Doc && (Doc.UserDoc().SelectedDocs = new List([Doc.LinkOtherAnchor(this.Document.links[0], this.props.Document)])); } else if (this.Document.isButton) { + console.log("button3"); + SelectionManager.SelectDoc(this, e.ctrlKey); // don't think this should happen if a button action is actually triggered. this.buttonClick(e.altKey, e.ctrlKey); } else { @@ -465,6 +479,7 @@ export class DocumentView extends DocComponent(Docu } onPointerDown = (e: React.PointerEvent): void => { + console.log("ting"); if (this.onPointerDownHandler && this.onPointerDownHandler.script) { this.onPointerDownHandler.script.run({ this: this.Document.isTemplateForField && this.props.DataDoc ? this.props.DataDoc : this.props.Document }, console.log); document.removeEventListener("pointerup", this.onPointerUp); diff --git a/src/client/views/nodes/QueryBox.tsx b/src/client/views/nodes/QueryBox.tsx index b2f9ca8fe..995effd1b 100644 --- a/src/client/views/nodes/QueryBox.tsx +++ b/src/client/views/nodes/QueryBox.tsx @@ -1,12 +1,22 @@ import React = require("react"); import { library } from '@fortawesome/fontawesome-svg-core'; import { faArrowLeft, faArrowRight, faEdit, faMinus, faPlay, faPlus, faStop, faTimes } from '@fortawesome/free-solid-svg-icons'; -import { IReactionDisposer } from "mobx"; +import { IReactionDisposer, computed } from "mobx"; import { observer } from "mobx-react"; import { FilterBox } from "../search/FilterBox"; import { FieldView, FieldViewProps } from './FieldView'; import "./PresBox.scss"; import { SearchBox } from "../search/SearchBox"; +import { SelectionManager } from "../../util/SelectionManager"; +import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView"; +import { emptyFunction, returnOne } from "../../../Utils"; +import { DocAnnotatableComponent } from '../DocComponent'; +import { makeInterface, createSchema } from "../../../new_fields/Schema"; +import { documentSchema } from "../../../new_fields/documentSchemas"; +import { TraceMobx } from "../../../new_fields/util"; +import { Id } from '../../../new_fields/FieldSymbols'; + + library.add(faArrowLeft); library.add(faArrowRight); @@ -17,8 +27,19 @@ library.add(faTimes); library.add(faMinus); library.add(faEdit); +export const pageSchema = createSchema({ + curPage: "number", + fitWidth: "boolean", + googlePhotosUrl: "string", + googlePhotosTags: "string" +}); + + +type QueryDocument = makeInterface<[typeof pageSchema, typeof documentSchema]>; +const QueryDocument = makeInterface(pageSchema, documentSchema); + @observer -export class QueryBox extends React.Component { +export class QueryBox extends DocAnnotatableComponent(QueryDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(QueryBox, fieldKey); } _docListChangedReaction: IReactionDisposer | undefined; componentDidMount() { @@ -28,12 +49,38 @@ export class QueryBox extends React.Component { this._docListChangedReaction && this._docListChangedReaction(); } - render() { - return
-
- -
+ @computed get content() { + let key = this.props.Document[Id]; + return + } + contentFunc = () => [this.content]; + + render() { + const dragging = !SelectionManager.GetIsDragging() ? "" : "-dragging"; + return
+ {/* + {this.contentFunc} + */} + {this.contentFunc()}
; } } \ No newline at end of file diff --git a/src/client/views/search/IconButton.tsx b/src/client/views/search/IconButton.tsx index bea8cc0a7..4f94139d9 100644 --- a/src/client/views/search/IconButton.tsx +++ b/src/client/views/search/IconButton.tsx @@ -123,16 +123,19 @@ export class IconButton extends React.Component{ selected = { opacity: 1, - backgroundColor: "rgb(128, 128, 128)" + backgroundColor: "#121721", + //backgroundColor: "rgb(128, 128, 128)" }; notSelected = { opacity: 0.2, + backgroundColor: "#121721", }; hoverStyle = { opacity: 1, - backgroundColor: "rgb(178, 206, 248)" //$darker-alt-accent + backgroundColor: "rgb(128, 128, 128)" + //backgroundColor: "rgb(178, 206, 248)" //$darker-alt-accent }; @action.bound diff --git a/src/client/views/search/SearchBox.scss b/src/client/views/search/SearchBox.scss index 1b36912d1..1559efe09 100644 --- a/src/client/views/search/SearchBox.scss +++ b/src/client/views/search/SearchBox.scss @@ -44,6 +44,10 @@ &.searchBox-filter { align-self: stretch; + button:hover{ + transform:scale(1.0); + background:"#121721"; + } } &.searchBox-submit { @@ -88,7 +92,7 @@ .filter-form { position: relative; - background: black; + background: #121721; flex-direction: column; transform-origin: top; transition: height 0.3s ease, display 0.6s ease; @@ -112,6 +116,8 @@ .filter-item { position: relative; + border:1px solid grey; + border-radius: 16px; } } diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 2e7e95b60..ae8261861 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -22,8 +22,11 @@ import { FieldView } from '../nodes/FieldView'; library.add(faTimes); +export interface SearchProps { + id:string; +} @observer -export class SearchBox extends React.Component { +export class SearchBox extends React.Component { @observable private _searchString: string = ""; @observable private _resultsOpen: boolean = false; @@ -260,7 +263,7 @@ export class SearchBox extends React.Component { } //return Docs.Create.TreeDocument(docs, { _width: 200, _height: 400, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` }); //return Docs.Create.SearchDocument(docs, { _width: 200, _height: 400, searchText: this._searchString, title: `Search Docs: "${this._searchString}"` }); - return Docs.Create.QueryDocument({ + return Docs.Create.QueryDocument({_autoHeight: true, title: "-typed text-" }); } @@ -376,10 +379,10 @@ export class SearchBox extends React.Component { handleNodeChange = () => { this._nodeStatus = !this._nodeStatus; if (this._nodeStatus){ - this.expandSection("node") + this.expandSection(`node${this.props.id}`) } else{ - this.collapseSection("node") + this.collapseSection(`node${this.props.id}`) } } @@ -392,11 +395,11 @@ export class SearchBox extends React.Component { handleFilterChange=() =>{ this._filterOpen=!this._filterOpen; if (this._filterOpen){ - this.expandSection("filterhead"); - document.getElementById("filterhead")!.style.padding="5"; + this.expandSection(`filterhead${this.props.id}`); + document.getElementById(`filterhead${this.props.id}`)!.style.padding="5"; } else{ - this.collapseSection("filterhead"); + this.collapseSection(`filterhead${this.props.id}`); } @@ -411,6 +414,7 @@ export class SearchBox extends React.Component { collapseSection(thing:string) { + let id = this.props.id; let element= document.getElementById(thing)!; // get the height of the element's inner content, regardless of its actual size var sectionHeight = element.scrollHeight; @@ -430,7 +434,7 @@ export class SearchBox extends React.Component { // have the element transition to height: 0 requestAnimationFrame(function() { element.style.height = 0 + 'px'; - thing == "filterhead"? document.getElementById("filterhead")!.style.padding="0" : null; + thing == `filterhead${id}`? document.getElementById(`filterhead${id}`)!.style.padding="0" : null; }); }); @@ -478,7 +482,7 @@ export class SearchBox extends React.Component { render() { return ( -
{ e.stopPropagation(); e.preventDefault(); }}> +
this._searchString ? this.startDragCollection() : undefined)} ref={this.collectionRef} title="Drag Results as Collection"> @@ -489,13 +493,13 @@ export class SearchBox extends React.Component {
-
-
+
+
-
+
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 58958f1fc..8c357884e 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -204,7 +204,7 @@ export class CurrentUserUtils { _width: 50, _height: 25, backgroundColor: "lightgrey", color: "rgb(34, 34, 34)", title: "Search", fontSize: 10, letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)", sourcePanel: Docs.Create.QueryDocument({ - title: "search stack", ignoreClick: true + title: "search stack", }), targetContainer: sidebarContainer, lockedPosition: true, -- cgit v1.2.3-70-g09d2 From c71695328de0078c5f59bf50c994f1333e58e625 Mon Sep 17 00:00:00 2001 From: Andy Rickert Date: Wed, 1 Apr 2020 13:11:46 -0700 Subject: final UI changes and beginning to reimpliment filterbox backend in searchbox class --- src/client/views/search/SearchBox.scss | 36 ++++- src/client/views/search/SearchBox.tsx | 237 +++++++++++++++++++++++++++------ 2 files changed, 233 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/client/views/search/SearchBox.scss b/src/client/views/search/SearchBox.scss index 1559efe09..ec4eda643 100644 --- a/src/client/views/search/SearchBox.scss +++ b/src/client/views/search/SearchBox.scss @@ -103,6 +103,7 @@ .filter-header { display: flex; position: relative; + flex-wrap:wrap; right: 1px; color: grey; flex-direction: row-reverse; @@ -127,14 +128,45 @@ right: 1px; color: grey; transform-origin: top; - border-top: grey 1px solid; - padding-top: 5px; + border-top: 0px; + //padding-top: 5px; margin-left: 10px; margin-right: 10px; overflow:hidden; transition:height 0.3s ease-out; height:0px; + } + .filter-key { + position: relative; + right: 1px; + color: grey; + transform-origin: top; + border-top: 0px; + //padding-top: 5px; + margin-left: 10px; + margin-right: 10px; + overflow:hidden; + transition:height 0.3s ease-out; + height:0px; + .filter-keybar { + display: flex; + flex-wrap: wrap; + justify-content: space-evenly; + height: auto; + width: 100%; + flex-direction: row-reverse; + margin-top:5px; + + .filter-item { + position: relative; + border:1px solid grey; + border-radius: 16px; + + } + } + + } } diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index ae8261861..ed9deff15 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -7,24 +7,34 @@ import * as React from 'react'; 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 { Cast, NumCast, StrCast } from '../../../new_fields/Types'; import { Utils } from '../../../Utils'; import { Docs } from '../../documents/Documents'; import { SetupDrag } from '../../util/DragManager'; import { SearchUtil } from '../../util/SearchUtil'; -// import { FilterBox } from './FilterBox'; -// import "./FilterBox.scss"; import "./SearchBox.scss"; import { SearchItem } from './SearchItem'; import { IconBar } from './IconBar'; import { FieldFilters } from './FieldFilters'; import { FieldView } from '../nodes/FieldView'; +import { DocumentType } from "../../documents/DocumentTypes"; +import { DocumentView } from '../nodes/DocumentView'; +import { SelectionManager } from '../../util/SelectionManager'; + + library.add(faTimes); export interface SearchProps { id:string; } + +export enum Keys { + TITLE = "title", + AUTHOR = "author", + DATA = "data" +} + @observer export class SearchBox extends React.Component { @@ -59,11 +69,8 @@ export class SearchBox extends React.Component { constructor(props: any) { super(props); - SearchBox.Instance = this; this.resultsScrolled = this.resultsScrolled.bind(this); - //reaction(()=>document.getElementById("node")?.scrollHeight,()=>{console.log("longer")}) - } private _reactionDisposer?: IReactionDisposer; @@ -74,7 +81,6 @@ export class SearchBox extends React.Component { runInAction(() => { this._searchbarOpen = true; }); - } } @@ -126,17 +132,174 @@ export class SearchBox extends React.Component { } } + public _allIcons: string[] = [DocumentType.AUDIO, DocumentType.COL, DocumentType.IMG, DocumentType.LINK, DocumentType.PDF, DocumentType.TEXT, DocumentType.VID, DocumentType.WEB, DocumentType.TEMPLATE]; + //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 _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 _anyKeywordStatus: boolean = true; + @observable private _allKeywordStatus: boolean = true; + @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 public _deletedDocsStatus: boolean = false; + @observable private _collectionStatus = false; + @observable private _collectionSelfStatus = true; + @observable private _collectionParentStatus = true; + + + getFinalQuery(query: string): string { + //alters the query so it looks in the correct fields + //if this is true, then not all of the field boxes are checked + //TODO: data + if (this.fieldFiltersApplied) { + query = this.applyBasicFieldFilters(query); + query = query.replace(/\s+/g, ' ').trim(); + } + + //alters the query based on if all words or any words are required + //if this._wordstatus is false, all words are required and a + is added before each + if (!this._basicWordStatus) { + query = this.basicRequireWords(query); + query = query.replace(/\s+/g, ' ').trim(); + } + + //if should be searched in a specific collection + if (this._collectionStatus) { + query = this.addCollectionFilter(query); + query = query.replace(/\s+/g, ' ').trim(); + } + return query; + } + + basicRequireWords(query: string): string { + const oldWords = query.split(" "); + const newWords: string[] = []; + oldWords.forEach(word => { + const newWrd = "+" + word; + newWords.push(newWrd); + }); + query = newWords.join(" "); + + return query; + } + + @action + filterDocsByType(docs: Doc[]) { + if (this._icons.length === 9) { + return docs; + } + const finalDocs: Doc[] = []; + docs.forEach(doc => { + const layoutresult = Cast(doc.type, "string"); + if (layoutresult && this._icons.includes(layoutresult)) { + finalDocs.push(doc); + } + }); + return finalDocs; + } + + addCollectionFilter(query: string): string { + const collections: Doc[] = this.getCurCollections(); + const oldWords = query.split(" "); + + const collectionString: string[] = []; + collections.forEach(doc => { + const proto = doc.proto; + const protoId = (proto || doc)[Id]; + const colString: string = "{!join from=data_l to=id}id:" + protoId + " "; + collectionString.push(colString); + }); + + let finalColString = collectionString.join(" "); + finalColString = finalColString.trim(); + return "+(" + finalColString + ")" + query; + } + + get filterTypes() { + return this._icons.length === 9 ? undefined : this._icons; + } + + +//TODO: basically all of this + //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[] { + const selectedDocs: DocumentView[] = SelectionManager.SelectedDocuments(); + const collections: Doc[] = []; + + selectedDocs.forEach(async element => { + 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 + if (!collections.includes(element.props.Document)) { + collections.push(element.props.Document); + } + } + //makes sure collections aren't added more than once + if (element.props.ContainingCollectionDoc && !collections.includes(element.props.ContainingCollectionDoc)) { + collections.push(element.props.ContainingCollectionDoc); + } + }); + + return collections; + } + + + applyBasicFieldFilters(query: string) { + let finalQuery = ""; + + if (this._titleFieldStatus) { + finalQuery = finalQuery + this.basicFieldFilters(query, Keys.TITLE); + } + if (this._authorFieldStatus) { + finalQuery = finalQuery + this.basicFieldFilters(query, Keys.AUTHOR); + } + if (this._deletedDocsStatus) { + finalQuery = finalQuery + this.basicFieldFilters(query, Keys.DATA); + } + return finalQuery; + } + + basicFieldFilters(query: string, type: string): string { + const oldWords = query.split(" "); + let mod = ""; + + if (type === Keys.AUTHOR) { + mod = " author_t:"; + } if (type === Keys.DATA) { + //TODO + } if (type === Keys.TITLE) { + mod = " title_t:"; + } + + const newWords: string[] = []; + oldWords.forEach(word => { + const newWrd = mod + word; + newWords.push(newWrd); + }); + + query = newWords.join(" "); + + return query; + } + + get fieldFiltersApplied() { return !(this._authorFieldStatus && this._titleFieldStatus); } + + + @action submitSearch = async () => { let query = this._searchString; - // query = FilterBox.Instance.getFinalQuery(query); + this.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; } @@ -156,16 +319,16 @@ export class SearchBox extends React.Component { } getAllResults = async (query: string) => { - return SearchUtil.Search(query, true, { start: 0, rows: 10000000 }); + return SearchUtil.Search(query, true, { fq: this.filterQuery, start: 0, rows: 10000000 }); + } - //return SearchUtil.Search(query, true, { fq: this.filterQuery, start: 0, rows: 10000000 }); + private get filterQuery() { + const types = this.filterTypes; + const includeDeleted = this.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(" ")})` : ""); } + getDataStatus() { return this._deletedDocsStatus; } - // 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; @@ -176,9 +339,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: this.NumResults, hl: true, "hl.fl": "*" }).then(action(async (res: SearchUtil.DocSearchResult) => { - this._curRequest = SearchUtil.Search(query, true, { start: this._maxSearchIndex, rows: this.NumResults, 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) { this._numTotalResults = res.numFound; @@ -191,10 +352,9 @@ 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]); - //const filteredDocs = FilterBox.Instance.filterDocsByType(docs); - const filteredDocs = docs; + const filteredDocs = this.filterDocsByType(docs); runInAction(() => { - // this._results.push(...filteredDocs); + //this._results.push(...filteredDocs); filteredDocs.forEach(doc => { const index = this._resultsSet.get(doc); const highlight = highlights[doc[Id]]; @@ -224,12 +384,8 @@ export class SearchBox extends React.Component { collectionRef = React.createRef(); startDragCollection = async () => { - //const res = await this.getAllResults(FilterBox.Instance.getFinalQuery(this._searchString)); - const res = await this.getAllResults(this._searchString); - - //const filtered = FilterBox.Instance.filterDocsByType(res.docs); - const filtered = res.docs; - // console.log(this._results) + const res = await this.getAllResults(this.getFinalQuery(this._searchString)); + const filtered = this.filterDocsByType(res.docs); const docs = filtered.map(doc => { const isProto = Doc.GetT(doc, "isPrototype", "boolean", true); if (isProto) { @@ -271,15 +427,12 @@ export class SearchBox extends React.Component { 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; } @@ -367,8 +520,6 @@ export class SearchBox extends React.Component { @computed get resultHeight() { return this._numTotalResults * 70; } - @observable private _filterOpen: boolean = false; - //if true, any keywords can be used. if false, all keywords are required. @action.bound handleWordQueryChange = () => { @@ -389,6 +540,12 @@ export class SearchBox extends React.Component { @action.bound handleKeyChange = () => { this._keyStatus = !this._keyStatus; + if (this._keyStatus){ + this.expandSection(`key${this.props.id}`); + } + else{ + this.collapseSection(`key${this.props.id}`); + } } @action.bound @@ -499,11 +656,15 @@ export class SearchBox extends React.Component {
-
+
-
- +
+
+ + + +
-- cgit v1.2.3-70-g09d2 From 3a1dac48c00dbe81142da90f8b52bfae02ce1921 Mon Sep 17 00:00:00 2001 From: Andy Rickert Date: Wed, 1 Apr 2020 18:11:08 -0700 Subject: fixed backend filter and passing search query to new doc --- src/client/documents/Documents.ts | 4 +++- src/client/views/nodes/QueryBox.tsx | 15 ++++++++++++-- src/client/views/search/SearchBox.tsx | 37 ++++++++++++++++++++++++++++++----- 3 files changed, 48 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 247f7fa3e..948433bd1 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -146,7 +146,8 @@ export interface DocumentOptions { selectedIndex?: number; syntaxColor?: string; // can be applied to text for syntax highlighting all matches in the text searchText?: string, //for searchbox - + sq?: string, + fq?: string, } class EmptyBox { @@ -459,6 +460,7 @@ export namespace Docs { } export function QueryDocument(options: DocumentOptions = {}) { + console.log("yuh"); return InstanceFromProto(Prototypes.get(DocumentType.QUERY), "", options); } diff --git a/src/client/views/nodes/QueryBox.tsx b/src/client/views/nodes/QueryBox.tsx index 995effd1b..95ea3e099 100644 --- a/src/client/views/nodes/QueryBox.tsx +++ b/src/client/views/nodes/QueryBox.tsx @@ -3,7 +3,6 @@ import { library } from '@fortawesome/fontawesome-svg-core'; import { faArrowLeft, faArrowRight, faEdit, faMinus, faPlay, faPlus, faStop, faTimes } from '@fortawesome/free-solid-svg-icons'; import { IReactionDisposer, computed } from "mobx"; import { observer } from "mobx-react"; -import { FilterBox } from "../search/FilterBox"; import { FieldView, FieldViewProps } from './FieldView'; import "./PresBox.scss"; import { SearchBox } from "../search/SearchBox"; @@ -15,6 +14,7 @@ import { makeInterface, createSchema } from "../../../new_fields/Schema"; import { documentSchema } from "../../../new_fields/documentSchemas"; import { TraceMobx } from "../../../new_fields/util"; import { Id } from '../../../new_fields/FieldSymbols'; +import { StrCast } from "../../../new_fields/Types"; @@ -51,7 +51,18 @@ export class QueryBox extends DocAnnotatableComponent + let sq = StrCast(this.props.Document.sq); + let fq= StrCast(this.props.Document.fq); + if (this.props.Document.sq){ + console.log("yes"); + console.log(sq); + console.log(fq); + return + } + else { + console.log("no"); + return + } } contentFunc = () => [this.content]; diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index ed9deff15..56b769396 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -27,6 +27,8 @@ library.add(faTimes); export interface SearchProps { id:string; + sq?:string; + fq?:string; } export enum Keys { @@ -82,6 +84,16 @@ export class SearchBox extends React.Component { this._searchbarOpen = true; }); } + if (this.props.sq && this.props.fq){ + console.log(this.props.sq); + let sq= this.props.sq + + let fq =this.props.fq; + runInAction(() => { + this._searchString=sq; + this.submitSearch(); + }); + } } @@ -223,6 +235,11 @@ export class SearchBox extends React.Component { return this._icons.length === 9 ? undefined : this._icons; } + @action.bound + updateIcon(newArray: string[]) { this._icons = newArray; } + + @action.bound + getIcons(): string[] { return this._icons; } //TODO: basically all of this //gets all of the collections of all the docviews that are selected @@ -327,6 +344,7 @@ export class SearchBox extends React.Component { const includeDeleted = this.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(" ")})` : ""); } + getDataStatus() { return this._deletedDocsStatus; } @@ -417,9 +435,10 @@ export class SearchBox extends React.Component { y += 300; } } + console.log("create"); //return Docs.Create.TreeDocument(docs, { _width: 200, _height: 400, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` }); //return Docs.Create.SearchDocument(docs, { _width: 200, _height: 400, searchText: this._searchString, title: `Search Docs: "${this._searchString}"` }); - return Docs.Create.QueryDocument({_autoHeight: true, title: "-typed text-" + return Docs.Create.QueryDocument({_autoHeight: true, title: this._searchString, fq: this.filterQuery, sq: this._searchString, }); } @@ -633,9 +652,17 @@ export class SearchBox extends React.Component { // remove "height" from the element's inline styles, so it can return to its initial value element.style.height="auto"; //element.style.height = undefined; - } + @action.bound + updateTitleStatus() { this._titleFieldStatus = !this._titleFieldStatus; } + + @action.bound + updateAuthorStatus() { this._authorFieldStatus = !this._authorFieldStatus; } + + @action.bound + updateDataStatus() { this._deletedDocsStatus = !this._deletedDocsStatus; } + render() { return ( @@ -661,9 +688,9 @@ export class SearchBox extends React.Component {
- - - + + +
-- cgit v1.2.3-70-g09d2 From 9d06cd45c732006ed5ee13734fa8145886e349c0 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 3 Apr 2020 16:45:22 -0400 Subject: fixed some issues with template buttons creating documents. simplified query boxe code. added a searchView. --- src/client/documents/Documents.ts | 5 +- src/client/views/TemplateMenu.tsx | 12 +- src/client/views/nodes/QueryBox.scss | 6 + src/client/views/nodes/QueryBox.tsx | 87 ++------ src/client/views/search/SearchBox.tsx | 226 ++++++++------------- .../authentication/models/current_user_utils.ts | 10 +- 6 files changed, 124 insertions(+), 222 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index da8efe745..89e8d7ebc 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -164,8 +164,8 @@ export interface DocumentOptions { selectedIndex?: number; syntaxColor?: string; // can be applied to text for syntax highlighting all matches in the text searchText?: string, //for searchbox - sq?: string, - fq?: string, + searchQuery?: string, // for queryBox + filterQuery?: string, linearViewIsExpanded?: boolean; // is linear view expanded } @@ -548,7 +548,6 @@ export namespace Docs { } export function QueryDocument(options: DocumentOptions = {}) { - console.log("yuh"); return InstanceFromProto(Prototypes.get(DocumentType.QUERY), "", options); } diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 8eb5c5050..87ffb432d 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -124,7 +124,7 @@ export class TemplateMenu extends React.Component { templateMenu.push(); templateMenu.push(); if (noteTypesDoc) { - addedTypes.concat(noteTypes).map(template => template.treeViewChecked = ComputedField.MakeFunction("templateIsUsed(this, firstDoc)", { firstDoc: "string" }, { firstDoc: StrCast(firstDoc.title) })); + addedTypes.concat(noteTypes).map(template => template.treeViewChecked = ComputedField.MakeFunction(`templateIsUsed(this, "${StrCast(firstDoc.title)}")`, { firstDoc: "string" })); this._addedKeys && Array.from(this._addedKeys).filter(key => !noteTypes.some(nt => nt.title === key)).forEach(template => templateMenu.push( this.toggleLayout(e, template)} />)); templateMenu.push( @@ -174,10 +174,12 @@ Scripting.addGlobal(function switchView(doc: Doc, template: Doc) { return templateTitle && DocumentView.makeCustomViewClicked(doc, Docs.Create.FreeformDocument, templateTitle, template); }); -Scripting.addGlobal(function templateIsUsed(templateDoc: Doc, firstDocTitlte: string) { +Scripting.addGlobal(function templateIsUsed(templateDoc: Doc, firstDocTitle: string) { const firstDoc = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0].props.Document : undefined; - if (!firstDoc) return false; - const template = StrCast(templateDoc.dragFactory ? Cast(templateDoc.dragFactory, Doc, null)?.title : templateDoc.title); - return StrCast(firstDoc.layoutKey) === "layout_" + template ? 'check' : 'unchecked'; + if (firstDoc) { + const template = StrCast(templateDoc.dragFactory ? Cast(templateDoc.dragFactory, Doc, null)?.title : templateDoc.title); + return StrCast(firstDoc.layoutKey) === "layout_" + template ? 'check' : 'unchecked'; + } + return false; // return SelectionManager.SelectedDocuments().some(view => StrCast(view.props.Document.layoutKey) === "layout_" + template) ? 'check' : 'unchecked' }); \ No newline at end of file diff --git a/src/client/views/nodes/QueryBox.scss b/src/client/views/nodes/QueryBox.scss index e69de29bb..82f64054c 100644 --- a/src/client/views/nodes/QueryBox.scss +++ b/src/client/views/nodes/QueryBox.scss @@ -0,0 +1,6 @@ +.queryBox, .queryBox-dragging { + width: 100%; + height: 100%; + position: absolute; + pointer-events: all; +} \ No newline at end of file diff --git a/src/client/views/nodes/QueryBox.tsx b/src/client/views/nodes/QueryBox.tsx index 95ea3e099..566c07dfe 100644 --- a/src/client/views/nodes/QueryBox.tsx +++ b/src/client/views/nodes/QueryBox.tsx @@ -1,42 +1,18 @@ import React = require("react"); -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faArrowLeft, faArrowRight, faEdit, faMinus, faPlay, faPlus, faStop, faTimes } from '@fortawesome/free-solid-svg-icons'; -import { IReactionDisposer, computed } from "mobx"; +import { IReactionDisposer } from "mobx"; import { observer } from "mobx-react"; -import { FieldView, FieldViewProps } from './FieldView'; -import "./PresBox.scss"; -import { SearchBox } from "../search/SearchBox"; -import { SelectionManager } from "../../util/SelectionManager"; -import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView"; -import { emptyFunction, returnOne } from "../../../Utils"; -import { DocAnnotatableComponent } from '../DocComponent'; -import { makeInterface, createSchema } from "../../../new_fields/Schema"; import { documentSchema } from "../../../new_fields/documentSchemas"; -import { TraceMobx } from "../../../new_fields/util"; import { Id } from '../../../new_fields/FieldSymbols'; +import { makeInterface } from "../../../new_fields/Schema"; import { StrCast } from "../../../new_fields/Types"; +import { SelectionManager } from "../../util/SelectionManager"; +import { DocAnnotatableComponent } from '../DocComponent'; +import { SearchBox } from "../search/SearchBox"; +import { FieldView, FieldViewProps } from './FieldView'; +import "./QueryBox.scss"; - - -library.add(faArrowLeft); -library.add(faArrowRight); -library.add(faPlay); -library.add(faStop); -library.add(faPlus); -library.add(faTimes); -library.add(faMinus); -library.add(faEdit); - -export const pageSchema = createSchema({ - curPage: "number", - fitWidth: "boolean", - googlePhotosUrl: "string", - googlePhotosTags: "string" -}); - - -type QueryDocument = makeInterface<[typeof pageSchema, typeof documentSchema]>; -const QueryDocument = makeInterface(pageSchema, documentSchema); +type QueryDocument = makeInterface<[typeof documentSchema]>; +const QueryDocument = makeInterface(documentSchema); @observer export class QueryBox extends DocAnnotatableComponent(QueryDocument) { @@ -46,52 +22,13 @@ export class QueryBox extends DocAnnotatableComponent - } - else { - console.log("no"); - return - } + this._docListChangedReaction?.(); } - contentFunc = () => [this.content]; - render() { const dragging = !SelectionManager.GetIsDragging() ? "" : "-dragging"; - return
- {/* - {this.contentFunc} - */} - {this.contentFunc()} + return
+
; } } \ No newline at end of file diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 56b769396..e7941a9ba 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -15,20 +15,17 @@ import { SearchUtil } from '../../util/SearchUtil'; import "./SearchBox.scss"; import { SearchItem } from './SearchItem'; import { IconBar } from './IconBar'; -import { FieldFilters } from './FieldFilters'; import { FieldView } from '../nodes/FieldView'; import { DocumentType } from "../../documents/DocumentTypes"; import { DocumentView } from '../nodes/DocumentView'; import { SelectionManager } from '../../util/SelectionManager'; - - library.add(faTimes); export interface SearchProps { - id:string; - sq?:string; - fq?:string; + id: string; + searchQuery?: string; + filterQquery?: string; } export enum Keys { @@ -44,11 +41,11 @@ export class SearchBox extends React.Component { @observable private _resultsOpen: boolean = false; @observable private _searchbarOpen: boolean = false; @observable private _results: [Doc, string[], string[]][] = []; - private _resultsSet = new Map(); @observable private _openNoResults: boolean = false; @observable private _visibleElements: JSX.Element[] = []; - private resultsRef = React.createRef(); + private _resultsSet = new Map(); + private _resultsRef = React.createRef(); public inputRef = React.createRef(); private _isSearch: ("search" | "placeholder" | undefined)[] = []; @@ -75,22 +72,16 @@ export class SearchBox extends React.Component { this.resultsScrolled = this.resultsScrolled.bind(this); } - private _reactionDisposer?: IReactionDisposer; - componentDidMount = () => { if (this.inputRef.current) { this.inputRef.current.focus(); - runInAction(() => { - this._searchbarOpen = true; - }); + runInAction(() => this._searchbarOpen = true); } - if (this.props.sq && this.props.fq){ - console.log(this.props.sq); - let sq= this.props.sq - - let fq =this.props.fq; + if (this.props.searchQuery && this.props.filterQquery) { + console.log(this.props.searchQuery); + const sq = this.props.searchQuery; runInAction(() => { - this._searchString=sq; + this._searchString = sq; this.submitSearch(); }); } @@ -99,12 +90,7 @@ export class SearchBox extends React.Component { @action getViews = async (doc: Doc) => { - const results = await SearchUtil.GetViewsOfDocument(doc); - let toReturn: Doc[] = []; - await runInAction(() => { - toReturn = results; - }); - return toReturn; + return await SearchUtil.GetViewsOfDocument(doc); } @action.bound @@ -241,7 +227,7 @@ export class SearchBox extends React.Component { @action.bound getIcons(): string[] { return this._icons; } -//TODO: basically all of this + //TODO: basically all of this //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[] { @@ -308,7 +294,6 @@ export class SearchBox extends React.Component { get fieldFiltersApplied() { return !(this._authorFieldStatus && this._titleFieldStatus); } - @action submitSearch = async () => { let query = this._searchString; @@ -317,22 +302,19 @@ export class SearchBox extends React.Component { this._resultsSet.clear(); this._isSearch = []; this._visibleElements = []; - if (query === "") { - return; - } - else { + if (query !== "") { 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(); - }); + runInAction(() => { + this._resultsOpen = true; + this._searchbarOpen = true; + this._openNoResults = true; + this.resultsScrolled(); + }); + } } getAllResults = async (query: string) => { @@ -348,7 +330,6 @@ export class SearchBox extends React.Component { getDataStatus() { return this._deletedDocsStatus; } - private NumResults = 25; private lockPromise?: Promise; getResults = async (query: string) => { @@ -438,8 +419,7 @@ export class SearchBox extends React.Component { console.log("create"); //return Docs.Create.TreeDocument(docs, { _width: 200, _height: 400, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` }); //return Docs.Create.SearchDocument(docs, { _width: 200, _height: 400, searchText: this._searchString, title: `Search Docs: "${this._searchString}"` }); - return Docs.Create.QueryDocument({_autoHeight: true, title: this._searchString, fq: this.filterQuery, sq: this._searchString, - }); + return Docs.Create.QueryDocument({ _autoHeight: true, title: this._searchString, filterQuery: this.filterQuery, searchQuery: this._searchString }); } @action.bound @@ -469,11 +449,11 @@ export class SearchBox extends React.Component { @action resultsScrolled = (e?: React.UIEvent) => { - if (!this.resultsRef.current) return; - const scrollY = e ? e.currentTarget.scrollTop : this.resultsRef.current ? this.resultsRef.current.scrollTop : 0; + 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))); + const endIndex = Math.ceil(Math.min(this._numTotalResults - 1, startIndex + (this._resultsRef.current.getBoundingClientRect().height / itemHght))); this._endIndex = endIndex === -1 ? 12 : endIndex; @@ -548,10 +528,10 @@ export class SearchBox extends React.Component { @action.bound handleNodeChange = () => { this._nodeStatus = !this._nodeStatus; - if (this._nodeStatus){ + if (this._nodeStatus) { this.expandSection(`node${this.props.id}`) } - else{ + else { this.collapseSection(`node${this.props.id}`) } } @@ -559,109 +539,107 @@ export class SearchBox extends React.Component { @action.bound handleKeyChange = () => { this._keyStatus = !this._keyStatus; - if (this._keyStatus){ + if (this._keyStatus) { this.expandSection(`key${this.props.id}`); } - else{ + else { this.collapseSection(`key${this.props.id}`); } } - @action.bound - handleFilterChange=() =>{ - this._filterOpen=!this._filterOpen; - if (this._filterOpen){ + @action.bound + handleFilterChange = () => { + this._filterOpen = !this._filterOpen; + if (this._filterOpen) { this.expandSection(`filterhead${this.props.id}`); - document.getElementById(`filterhead${this.props.id}`)!.style.padding="5"; + document.getElementById(`filterhead${this.props.id}`)!.style.padding = "5"; } - else{ + else { this.collapseSection(`filterhead${this.props.id}`); - + } } - // @observable - // private menuHeight= 0; @computed - get menuHeight(){ + get menuHeight() { return document.getElementById("hi")?.clientHeight; } - collapseSection(thing:string) { + collapseSection(thing: string) { let id = this.props.id; - let element= document.getElementById(thing)!; + let element = document.getElementById(thing)!; // get the height of the element's inner content, regardless of its actual size var sectionHeight = element.scrollHeight; - + // temporarily disable all css transitions var elementTransition = element.style.transition; element.style.transition = ''; - + // on the next frame (as soon as the previous style change has taken effect), // explicitly set the element's height to its current pixel height, so we // aren't transitioning out of 'auto' - requestAnimationFrame(function() { - element.style.height = sectionHeight + 'px'; - element.style.transition = elementTransition; - - // on the next frame (as soon as the previous style change has taken effect), - // have the element transition to height: 0 - requestAnimationFrame(function() { - element.style.height = 0 + 'px'; - thing == `filterhead${id}`? document.getElementById(`filterhead${id}`)!.style.padding="0" : null; - }); + requestAnimationFrame(function () { + element.style.height = sectionHeight + 'px'; + element.style.transition = elementTransition; + + // on the next frame (as soon as the previous style change has taken effect), + // have the element transition to height: 0 + requestAnimationFrame(function () { + element.style.height = 0 + 'px'; + thing == `filterhead${id}` ? document.getElementById(`filterhead${id}`)!.style.padding = "0" : null; + }); }); - + // mark the section as "currently collapsed" element.setAttribute('data-collapsed', 'true'); - } - - expandSection(thing:string) { + } + + expandSection(thing: string) { console.log("expand"); - let element= document.getElementById(thing)!; + let element = document.getElementById(thing)!; // get the height of the element's inner content, regardless of its actual size var sectionHeight = element.scrollHeight; - + // have the element transition to the height of its inner content - let temp = element.style.height; + let temp = element.style.height; element.style.height = sectionHeight + 'px'; - + // when the next css transition finishes (which should be the one we just triggered) element.addEventListener('transitionend', function handler(e) { - // remove this event listener so it only gets triggered once - console.log("autoset"); - element.removeEventListener('transitionend', handler); - - // remove "height" from the element's inline styles, so it can return to its initial value - element.style.height="auto"; - //element.style.height = undefined; + // remove this event listener so it only gets triggered once + console.log("autoset"); + element.removeEventListener('transitionend', handler); + + // remove "height" from the element's inline styles, so it can return to its initial value + element.style.height = "auto"; + //element.style.height = undefined; }); - + // mark the section as "currently not collapsed" element.setAttribute('data-collapsed', 'false'); - - } - autoset(thing: string){ - let element= document.getElementById(thing)!; + } + + autoset(thing: string) { + let element = document.getElementById(thing)!; console.log("autoset"); - element.removeEventListener('transitionend', function(e){}); - + element.removeEventListener('transitionend', function (e) { }); + // remove "height" from the element's inline styles, so it can return to its initial value - element.style.height="auto"; + element.style.height = "auto"; //element.style.height = undefined; - } + } + + @action.bound + updateTitleStatus() { this._titleFieldStatus = !this._titleFieldStatus; } + + @action.bound + updateAuthorStatus() { this._authorFieldStatus = !this._authorFieldStatus; } - @action.bound - updateTitleStatus() { this._titleFieldStatus = !this._titleFieldStatus; } - - @action.bound - updateAuthorStatus() { this._authorFieldStatus = !this._authorFieldStatus; } - - @action.bound - updateDataStatus() { this._deletedDocsStatus = !this._deletedDocsStatus; } + @action.bound + updateDataStatus() { this._deletedDocsStatus = !this._deletedDocsStatus; } render() { @@ -678,55 +656,27 @@ export class SearchBox extends React.Component {
-
+
-
+
-
+
- - + +
- - - {/*
-
-
-
Required words
-
-
- -
-
-
-
-
Filter by type of node
-
-
-
-
-
-
Filter by Basic Keys
-
-
-
-
-
-
*/}
+ }} ref={this._resultsRef}> {this._visibleElements}
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 31667cbdc..d55d996d3 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -280,6 +280,13 @@ export class CurrentUserUtils { /// sets up the default list of buttons to be shown in the expanding button menu at the bottom of the Dash window static setupExpandingButtons(doc: Doc) { + const queryTemplate = Docs.Create.MultirowDocument( + [ + Docs.Create.QueryDocument({ title: "query", _height: 200 }), + Docs.Create.FreeformDocument([], { title: "data", _height: 100 }) + ], + { _width: 400, _height: 300, title: "queryView", _chromeStatus: "disabled", _xMargin: 3, _yMargin: 3, _autoHeight: false }); + queryTemplate.isTemplateDoc = makeTemplate(queryTemplate); const slideTemplate = Docs.Create.MultirowDocument( [ Docs.Create.MulticolumnDocument([], { title: "data", _height: 200 }), @@ -303,7 +310,8 @@ export class CurrentUserUtils { doc.redoBtn = ficon({ onClick: ScriptField.MakeScript("redo()"), title: "redo button", icon: "redo-alt" }); doc.slidesBtn = ficon({ onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), dragFactory: slideTemplate, removeDropProperties: new List(["dropAction"]), title: "presentation slide", icon: "sticky-note" }); doc.descriptionBtn = ficon({ onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), dragFactory: descriptionTemplate, removeDropProperties: new List(["dropAction"]), title: "description view", icon: "sticky-note" }); - doc.templateButtons = blist({ title: "template buttons" }, [doc.slidesBtn as Doc, doc.descriptionBtn as Doc]); + doc.queryBtn = ficon({ onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), dragFactory: queryTemplate, removeDropProperties: new List(["dropAction"]), title: "query view", icon: "sticky-note" }); + doc.templateButtons = blist({ title: "template buttons" }, [doc.slidesBtn as Doc, doc.descriptionBtn as Doc, doc.queryBtn as Doc]); doc.expandingButtons = blist({ title: "expanding buttons" }, [doc.undoBtn as Doc, doc.redoBtn as Doc, doc.templateButtons as Doc]); doc.templateDocs = new PrefetchProxy(Docs.Create.TreeDocument([doc.noteTypes as Doc, doc.templateButtons as Doc], { title: "template layouts", _xPadding: 0, -- cgit v1.2.3-70-g09d2 From 5414cc78dfb650954c9b6fef8115a5945ea8d6a6 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 3 Apr 2020 17:50:24 -0400 Subject: changed dontSelect to dontDecorateSelection --- src/client/documents/Documents.ts | 2 +- src/client/util/DragManager.ts | 1 - src/client/util/SelectionManager.ts | 9 ++++++--- src/client/views/DocumentDecorations.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 8 +++----- src/new_fields/documentSchemas.ts | 2 +- src/server/authentication/models/current_user_utils.ts | 14 +++++++------- 7 files changed, 19 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 89e8d7ebc..a69bfae01 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -117,7 +117,7 @@ export interface DocumentOptions { lockedTransform?: boolean; // lock the panx,pany and scale parameters of the document so that it be panned/zoomed opacity?: number; defaultBackgroundColor?: string; - dontSelect?: boolean; // whether document decorations should be displayed when the document is selected + dontDecorateSelection?: boolean; // whether document decorations should be displayed when the document is selected isBackground?: boolean; isButton?: boolean; columnWidth?: number; diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 07cd2e98f..1f2312032 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -279,7 +279,6 @@ export namespace DragManager { } function StartDrag(eles: HTMLElement[], dragData: { [id: string]: any }, downX: number, downY: number, options?: DragOptions, finishDrag?: (dropData: DragCompleteEvent) => void) { - console.log("drag"); eles = eles.filter(e => e); if (!dragDiv) { dragDiv = document.createElement("div"); diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index b7d88c54c..7221fbbf9 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -14,7 +14,6 @@ export namespace SelectionManager { @action SelectDoc(docView: DocumentView, ctrlPressed: boolean): void { - console.log("select"); // if doc is not in SelectedDocuments, add it if (!manager.SelectedDocuments.get(docView)) { if (!ctrlPressed) { @@ -34,6 +33,7 @@ export namespace SelectionManager { @action DeselectDoc(docView: DocumentView): void { if (manager.SelectedDocuments.get(docView)) { + docView.dontDecorateSelection = false; manager.SelectedDocuments.delete(docView); docView.props.whenActiveChanged(false); Doc.UserDoc().SelectedDocs = new List(SelectionManager.SelectedDocuments().map(dv => dv.props.Document)); @@ -41,7 +41,10 @@ export namespace SelectionManager { } @action DeselectAll(): void { - Array.from(manager.SelectedDocuments.keys()).map(dv => dv.props.whenActiveChanged(false)); + Array.from(manager.SelectedDocuments.keys()).map(dv => { + dv.dontDecorateSelection = false; + dv.props.whenActiveChanged(false); + }); manager.SelectedDocuments.clear(); Doc.UserDoc().SelectedDocs = new List([]); } @@ -55,7 +58,7 @@ export namespace SelectionManager { export function SelectDoc(docView: DocumentView, ctrlPressed: boolean): void { manager.SelectDoc(docView, ctrlPressed); } - + export function IsSelected(doc: DocumentView, outsideReaction?: boolean): boolean { return outsideReaction ? diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 79600b7c1..c35263237 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -69,7 +69,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> get Bounds(): { x: number, y: number, b: number, r: number } { return SelectionManager.SelectedDocuments().reduce((bounds, documentView) => { if (documentView.props.renderDepth === 0 || - //documentView.props.Document.dontSelect || + documentView.dontDecorateSelection || Doc.AreProtosEqual(documentView.props.Document, CurrentUserUtils.UserDocument)) { return bounds; } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 75186f018..1e02ab44e 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -272,11 +272,11 @@ export class DocumentView extends DocComponent(Docu } } + dontDecorateSelection: any = false; onClick = (e: React.MouseEvent | React.PointerEvent) => { + this.dontDecorateSelection = this.props.Document.dontDecorateSelection && (!e.ctrlKey || e.button < 2); if (!e.nativeEvent.cancelBubble && !this.Document.ignoreClick && (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) { - console.log("click"); - e.stopPropagation(); let preventDefault = true; this.props.bringToFront(this.props.Document); @@ -294,12 +294,10 @@ export class DocumentView extends DocComponent(Docu this: this.props.Document, self: Cast(this.props.Document.rootDocument, Doc, null) || this.props.Document, containingCollection: this.props.ContainingCollectionDoc, shiftKey: e.shiftKey - }, console.log) && !this.props.Document.dontSelect && !this.props.Document.isButton && this.select(false), "on click"); + }, console.log) && !this.props.Document.dontDecorateSelection && !this.props.Document.isButton && this.select(false), "on click"); } else if (this.Document.type === DocumentType.BUTTON) { UndoManager.RunInBatch(() => ScriptBox.EditButtonScript("On Button Clicked ...", this.props.Document, "onClick", e.clientX, e.clientY), "on button click"); } else if (this.Document.isButton) { - console.log("button3"); - SelectionManager.SelectDoc(this, e.ctrlKey); // don't think this should happen if a button action is actually triggered. UndoManager.RunInBatch(() => this.buttonClick(e.altKey, e.ctrlKey), "on link button follow"); } else { diff --git a/src/new_fields/documentSchemas.ts b/src/new_fields/documentSchemas.ts index 91ea32bee..4bf871d97 100644 --- a/src/new_fields/documentSchemas.ts +++ b/src/new_fields/documentSchemas.ts @@ -42,7 +42,7 @@ export const documentSchema = createSchema({ removeDropProperties: listSpec("string"), // properties that should be removed from the alias/copy/etc of this document when it is dropped isTemplateForField: "string",// when specifies a field key, then the containing document is a template that renders the specified field isBackground: "boolean", // whether document is a background element and ignores input events (can only selet with marquee) - dontSelect: "boolean", // whether document should be selected when clicked (usually set to false for buttons) + dontDecorateSelection: "boolean", // whether document should be selected when clicked (usually set to false for buttons) treeViewOpen: "boolean", // flag denoting whether the documents sub-tree (contents) is visible or hidden treeViewExpandedView: "string", // name of field whose contents are being displayed as the document's subtree treeViewPreventOpen: "boolean", // ignores the treeViewOpen flag (for allowing a view to not be slaved to other views of the document) diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index d55d996d3..9a90ce17f 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -100,7 +100,7 @@ export class CurrentUserUtils { ignoreClick: data.ignoreClick, dropAction: data.click ? "copy" : undefined, onDragStart: data.drag ? ScriptField.MakeFunction(data.drag) : undefined, onClick: data.click ? ScriptField.MakeScript(data.click) : undefined, - ischecked: data.ischecked ? ComputedField.MakeFunction(data.ischecked) : undefined, activePen: data.activePen, dontSelect: true, + ischecked: data.ischecked ? ComputedField.MakeFunction(data.ischecked) : undefined, activePen: data.activePen, dontDecorateSelection: true, backgroundColor: data.backgroundColor, removeDropProperties: new List(["dropAction"]), dragFactory: data.dragFactory, })); } @@ -210,7 +210,7 @@ export class CurrentUserUtils { }); return Docs.Create.ButtonDocument({ - _width: 35, _height: 25, title: "Tools", fontSize: 10, targetContainer: sidebarContainer, dontSelect: true, + _width: 35, _height: 25, title: "Tools", fontSize: 10, targetContainer: sidebarContainer, dontDecorateSelection: true, letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)", sourcePanel: Docs.Create.StackingDocument([dragCreators, color], { _width: 500, lockedPosition: true, _chromeStatus: "disabled", title: "tools stack" @@ -236,7 +236,7 @@ export class CurrentUserUtils { }); return Docs.Create.ButtonDocument({ - _width: 50, _height: 25, title: "Library", fontSize: 10, dontSelect: true, + _width: 50, _height: 25, title: "Library", fontSize: 10, dontDecorateSelection: true, letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)", sourcePanel: Docs.Create.TreeDocument([doc.workspaces as Doc, doc.documents as Doc, Docs.Prototypes.MainLinkDocument(), doc, doc.recentlyClosed as Doc], { title: "Library", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "place", lockedPosition: true, boxShadow: "0 0", dontRegisterChildren: true @@ -249,7 +249,7 @@ export class CurrentUserUtils { // setup the Search button which will display the search panel. static setupSearchPanel(sidebarContainer: Doc) { return Docs.Create.ButtonDocument({ - _width: 50, _height: 25, title: "Search", fontSize: 10, dontSelect: true, + _width: 50, _height: 25, title: "Search", fontSize: 10, dontDecorateSelection: true, letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)", sourcePanel: Docs.Create.QueryDocument({ title: "search stack", @@ -283,7 +283,7 @@ export class CurrentUserUtils { const queryTemplate = Docs.Create.MultirowDocument( [ Docs.Create.QueryDocument({ title: "query", _height: 200 }), - Docs.Create.FreeformDocument([], { title: "data", _height: 100 }) + Docs.Create.FreeformDocument([], { title: "data", _height: 100, _LODdisable: true }) ], { _width: 400, _height: 300, title: "queryView", _chromeStatus: "disabled", _xMargin: 3, _yMargin: 3, _autoHeight: false }); queryTemplate.isTemplateDoc = makeTemplate(queryTemplate); @@ -298,10 +298,10 @@ export class CurrentUserUtils { Doc.GetProto(descriptionTemplate).layout = FormattedTextBox.LayoutString("description"); descriptionTemplate.isTemplateDoc = makeTemplate(descriptionTemplate, true, "descriptionView"); - const ficon = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({ ...opts, dontSelect: true, dropAction: "alias", removeDropProperties: new List(["dropAction"]), _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100 })) as any as Doc; + const ficon = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({ ...opts, dontDecorateSelection: true, dropAction: "alias", removeDropProperties: new List(["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", dontSelect: true, forceActive: true, + _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; -- cgit v1.2.3-70-g09d2 From adabfbea2b034beb310530aef9cc8b206e260b67 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 3 Apr 2020 20:23:15 -0400 Subject: added rootSelected() to make forceActive work better --- src/client/documents/Documents.ts | 2 +- src/client/util/RichTextSchema.tsx | 1 + src/client/views/DocComponent.tsx | 6 +++-- src/client/views/GestureOverlay.tsx | 1 + src/client/views/MainView.tsx | 4 ++++ src/client/views/OverlayView.tsx | 1 + src/client/views/Palette.tsx | 26 +++++++--------------- src/client/views/RecommendationsBox.tsx | 1 + src/client/views/SearchDocBox.tsx | 3 ++- .../views/collections/CollectionDockingView.tsx | 1 + .../views/collections/CollectionLinearView.tsx | 3 ++- .../views/collections/CollectionSchemaView.tsx | 1 + .../views/collections/CollectionStackingView.tsx | 1 + src/client/views/collections/CollectionSubView.tsx | 5 +++++ .../views/collections/CollectionTreeView.tsx | 2 ++ src/client/views/collections/CollectionView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 1 + .../collections/collectionFreeForm/MarqueeView.tsx | 1 - src/client/views/nodes/AudioBox.tsx | 12 +++++++--- .../views/nodes/CollectionFreeFormDocumentView.tsx | 7 +++--- .../views/nodes/ContentFittingDocumentView.tsx | 1 + src/client/views/nodes/DocumentBox.tsx | 1 + src/client/views/nodes/DocumentContentsView.tsx | 4 ++-- src/client/views/nodes/DocumentView.tsx | 24 +++++++++++++++----- src/client/views/nodes/FieldView.tsx | 1 + src/client/views/nodes/FormattedTextBoxComment.tsx | 1 + src/client/views/pdf/PDFViewer.tsx | 3 +-- .../views/presentationview/PresElementBox.tsx | 3 ++- src/client/views/search/SearchItem.tsx | 3 ++- src/mobile/MobileInterface.tsx | 2 ++ .../authentication/models/current_user_utils.ts | 2 +- 31 files changed, 83 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index a69bfae01..0a2269bac 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -435,7 +435,7 @@ export namespace Docs { Scripting.addGlobal(Buxton); const delegateKeys = ["x", "y", "layoutKey", "_width", "_height", "_panX", "_panY", "_viewType", "_nativeWidth", "_nativeHeight", "dropAction", "childDropAction", "_annotationOn", - "_chromeStatus", "_forceActive", "_autoHeight", "_fitWidth", "_LODdisable", "_itemIndex", "_showSidebar", "_showTitle", "_showCaption", "_showTitleHover", "_backgroundColor", + "_chromeStatus", "_autoHeight", "_fitWidth", "_LODdisable", "_itemIndex", "_showSidebar", "_showTitle", "_showCaption", "_showTitleHover", "_backgroundColor", "_xMargin", "_yMargin", "_xPadding", "_yPadding", "_singleLine", "_scrollTop", "_color", "isButton", "isBackground", "removeDropProperties", "treeViewOpen"]; diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index 094cd58f3..4a930177d 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -818,6 +818,7 @@ export class DashDocView { LibraryPath={this._textBox.props.LibraryPath} fitToBox={BoolCast(dashDoc._fitToBox)} addDocument={returnFalse} + rootSelected={this._textBox.props.isSelected} removeDocument={removeDoc} ScreenToLocalTransform={this.getDocTransform} addDocTab={this._textBox.props.addDocTab} diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index f4e830a48..454c245cc 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -29,6 +29,7 @@ interface DocExtendableProps { fieldKey: string; isSelected: (outsideReaction?: boolean) => boolean; renderDepth: number; + rootSelected: () => boolean; } export function DocExtendableComponent

(schemaCtor: (doc: Doc) => T) { class Component extends Touchable

{ @@ -36,7 +37,7 @@ export function DocExtendableComponent

(schemaCt @computed get Document(): T { return schemaCtor(this.props.Document); } @computed get layoutDoc() { return Doc.Layout(this.props.Document); } @computed get dataDoc() { return (this.props.DataDoc && (this.props.Document.isTemplateForField || this.props.Document.isTemplateDoc) ? this.props.DataDoc : Cast(this.props.Document.resolvedDataDoc, Doc, null) || Doc.GetProto(this.props.Document)) as Doc; } - active = (outsideReaction?: boolean) => !this.props.Document.isBackground && (this.props.Document.forceActive || this.props.isSelected(outsideReaction) || this.props.renderDepth === 0);// && !InkingControl.Instance.selectedTool; // bcz: inking state shouldn't affect static tools + active = (outsideReaction?: boolean) => !this.props.Document.isBackground && ((this.props.Document.forceActive && this.props.rootSelected()) || this.props.isSelected(outsideReaction) || this.props.renderDepth === 0);// && !InkingControl.Instance.selectedTool; // bcz: inking state shouldn't affect static tools } return Component; } @@ -50,6 +51,7 @@ export interface DocAnnotatableProps { active: () => boolean; whenActiveChanged: (isActive: boolean) => void; isSelected: (outsideReaction?: boolean) => boolean; + rootSelected: () => boolean; renderDepth: number; } export function DocAnnotatableComponent

(schemaCtor: (doc: Doc) => T) { @@ -86,7 +88,7 @@ export function DocAnnotatableComponent

(schema whenActiveChanged = action((isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive)); active = (outsideReaction?: boolean) => ((InkingControl.Instance.selectedTool === InkTool.None && !this.props.Document.isBackground) && - (this.props.Document.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false) + ((this.props.Document.forceActive && this.props.rootSelected()) || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false) annotationsActive = (outsideReaction?: boolean) => (InkingControl.Instance.selectedTool !== InkTool.None || (this.props.Document.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false) } diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index ea60907f6..26bee9a6f 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -705,6 +705,7 @@ export default class GestureOverlay extends Touchable { LibraryPath={emptyPath} addDocument={undefined} addDocTab={returnFalse} + rootSelected={returnTrue} pinToPres={emptyFunction} onClick={undefined} removeDocument={undefined} diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 8d9be5980..fae520e40 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -309,6 +309,7 @@ export class MainView extends React.Component { addDocument={undefined} addDocTab={this.addDocTabFunc} pinToPres={emptyFunction} + rootSelected={returnTrue} onClick={undefined} backgroundColor={this.defaultBackgroundColors} removeDocument={undefined} @@ -407,6 +408,7 @@ export class MainView extends React.Component { DataDoc={undefined} LibraryPath={emptyPath} addDocument={undefined} + rootSelected={returnTrue} addDocTab={this.addDocTabFunc} pinToPres={emptyFunction} removeDocument={undefined} @@ -435,6 +437,7 @@ export class MainView extends React.Component { addDocument={undefined} addDocTab={this.addDocTabFunc} pinToPres={emptyFunction} + rootSelected={returnTrue} removeDocument={returnFalse} onClick={undefined} ScreenToLocalTransform={this.mainContainerXf} @@ -523,6 +526,7 @@ export class MainView extends React.Component { fieldKey={"data"} dropAction={"alias"} annotationsKey={""} + rootSelected={returnTrue} bringToFront={emptyFunction} select={emptyFunction} active={returnFalse} diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index 220efd4a8..7587071db 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -174,6 +174,7 @@ export class OverlayView extends React.Component { Document={d} LibraryPath={emptyPath} ChromeHeight={returnZero} + rootSelected={returnTrue} // isSelected={returnFalse} // select={emptyFunction} // layoutKey={"layout"} diff --git a/src/client/views/Palette.tsx b/src/client/views/Palette.tsx index e04f814d1..674b27918 100644 --- a/src/client/views/Palette.tsx +++ b/src/client/views/Palette.tsx @@ -1,23 +1,12 @@ +import { IReactionDisposer, observable, reaction } from "mobx"; +import { observer } from "mobx-react"; import * as React from "react"; -import "./Palette.scss"; -import { PointData } from "../../new_fields/InkField"; import { Doc } from "../../new_fields/Doc"; -import { Docs } from "../documents/Documents"; -import { ScriptField, ComputedField } from "../../new_fields/ScriptField"; -import { List } from "../../new_fields/List"; -import { DocumentView } from "./nodes/DocumentView"; -import { emptyPath, returnFalse, emptyFunction, returnOne, returnEmptyString, returnTrue } from "../../Utils"; -import { CurrentUserUtils } from "../../server/authentication/models/current_user_utils"; +import { NumCast } from "../../new_fields/Types"; +import { emptyFunction, emptyPath, returnEmptyString, returnFalse, returnOne, returnTrue } from "../../Utils"; import { Transform } from "../util/Transform"; -import { computed, action, IReactionDisposer, reaction, observable } from "mobx"; -import { FieldValue, Cast, NumCast } from "../../new_fields/Types"; -import { observer } from "mobx-react"; -import { DocumentContentsView } from "./nodes/DocumentContentsView"; -import { CollectionStackingView } from "./collections/CollectionStackingView"; -import { CollectionView } from "./collections/CollectionView"; -import { CollectionSubView, SubCollectionViewProps } from "./collections/CollectionSubView"; -import { makeInterface } from "../../new_fields/Schema"; -import { documentSchema } from "../../new_fields/documentSchemas"; +import { DocumentView } from "./nodes/DocumentView"; +import "./Palette.scss"; export interface PaletteProps { x: number; @@ -40,7 +29,7 @@ export default class Palette extends React.Component { } componentWillUnmount = () => { - this._selectedDisposer && this._selectedDisposer(); + this._selectedDisposer?.(); } render() { @@ -54,6 +43,7 @@ export default class Palette extends React.Component { LibraryPath={emptyPath} addDocument={undefined} addDocTab={returnFalse} + rootSelected={returnTrue} pinToPres={emptyFunction} removeDocument={undefined} onClick={undefined} diff --git a/src/client/views/RecommendationsBox.tsx b/src/client/views/RecommendationsBox.tsx index 5ebba0abb..bf8de36b4 100644 --- a/src/client/views/RecommendationsBox.tsx +++ b/src/client/views/RecommendationsBox.tsx @@ -68,6 +68,7 @@ export class RecommendationsBox extends React.Component { addDocument={returnFalse} LibraryPath={emptyPath} removeDocument={returnFalse} + rootSelected={returnFalse} ScreenToLocalTransform={Transform.Identity} addDocTab={returnFalse} pinToPres={returnFalse} diff --git a/src/client/views/SearchDocBox.tsx b/src/client/views/SearchDocBox.tsx index c57f9e737..e66de39d4 100644 --- a/src/client/views/SearchDocBox.tsx +++ b/src/client/views/SearchDocBox.tsx @@ -410,8 +410,9 @@ export class SearchDocBox extends React.Component {

- +
{ Document={document} DataDoc={resolvedDataDoc} bringToFront={emptyFunction} + rootSelected={returnTrue} addDocument={undefined} removeDocument={undefined} ContentScaling={this.contentScaling} diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx index 344605412..a6ada75b2 100644 --- a/src/client/views/collections/CollectionLinearView.tsx +++ b/src/client/views/collections/CollectionLinearView.tsx @@ -4,7 +4,7 @@ import * as React from 'react'; import { Doc, HeightSym, WidthSym } from '../../../new_fields/Doc'; import { makeInterface } from '../../../new_fields/Schema'; import { BoolCast, NumCast, StrCast, Cast } from '../../../new_fields/Types'; -import { emptyFunction, returnEmptyString, returnOne, returnTrue, Utils } from '../../../Utils'; +import { emptyFunction, returnEmptyString, returnOne, returnTrue, Utils, returnFalse } from '../../../Utils'; import { DragManager } from '../../util/DragManager'; import { Transform } from '../../util/Transform'; import "./CollectionLinearView.scss"; @@ -110,6 +110,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { moveDocument={this.props.moveDocument} addDocTab={this.props.addDocTab} pinToPres={emptyFunction} + rootSelected={this.props.isSelected} removeDocument={this.props.removeDocument} onClick={undefined} ScreenToLocalTransform={this.getTransform(dref)} diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 981438513..a1b541f74 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -124,6 +124,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { LibraryPath={this.props.LibraryPath} childDocs={this.childDocs} renderDepth={this.props.renderDepth} + rootSelected={this.rootSelected} PanelWidth={this.previewWidth} PanelHeight={this.previewHeight} getTransform={this.getPreviewTransform} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 076dd3629..d21e17bbc 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -176,6 +176,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { LibraryPath={this.props.LibraryPath} renderDepth={this.props.renderDepth + 1} fitToBox={this.props.fitToBox} + rootSelected={this.rootSelected} dropAction={StrCast(this.props.Document.childDropAction) as dropActionType} onClick={layoutDoc.isTemplateDoc ? this.onClickHandler : this.onChildClickHandler} PanelWidth={width} diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 70927cf22..d1d6ae3c1 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -34,6 +34,7 @@ export interface CollectionViewProps extends FieldViewProps { PanelHeight: () => number; VisibleHeight?: () => number; setPreviewCursor?: (func: (x: number, y: number, drag: boolean) => void) => void; + rootSelected: () => boolean; fieldKey: string; } @@ -95,6 +96,10 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: this.props.Document.resolvedDataDoc ? this.props.Document : Doc.GetProto(this.props.Document)); // if the layout document has a resolvedDataDoc, then we don't want to get its parent which would be the unexpanded template } + rootSelected = () => { + return this.props.isSelected() || (this.props.Document.rootDocument || this.props.Document.forceActive ? this.props.rootSelected() : false); + } + // The data field for rendering this collection will be on the this.props.Document unless we're rendering a template in which case we try to use props.DataDoc. // When a document has a DataDoc but it's not a template, then it contains its own rendering data, but needs to pass the DataDoc through // to its children which may be templates. diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 6ee48f11b..fc612c66d 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -373,6 +373,7 @@ class TreeView extends React.Component { DataDocument={this.templateDataDoc} LibraryPath={emptyPath} renderDepth={this.props.renderDepth + 1} + rootSelected={returnTrue} backgroundColor={this.props.backgroundColor} fitToBox={this.boundsOfCollectionDocument !== undefined} PanelWidth={this.docWidth} @@ -454,6 +455,7 @@ class TreeView extends React.Component { LibraryPath={this.props.libraryPath || []} addDocument={undefined} addDocTab={this.props.addDocTab} + rootSelected={returnTrue} pinToPres={emptyFunction} onClick={this.props.onChildClick || editTitle} dropAction={this.props.dropAction} diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index df1770ffe..3913ccd88 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -117,7 +117,7 @@ export class CollectionView extends Touchable { return viewField; } - active = (outsideReaction?: boolean) => this.props.isSelected(outsideReaction) || BoolCast(this.props.Document.forceActive) || this._isChildActive || this.props.renderDepth === 0; + active = (outsideReaction?: boolean) => this.props.isSelected(outsideReaction) || (this.props.rootSelected() && BoolCast(this.props.Document.forceActive)) || this._isChildActive || this.props.renderDepth === 0; whenActiveChanged = (isActive: boolean) => { this.props.whenActiveChanged(this._isChildActive = isActive); }; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 2871fe192..a164e1794 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -832,6 +832,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { Document: childLayout, LibraryPath: this.libraryPath, layoutKey: undefined, + rootSelected: this.rootSelected, dropAction: StrCast(this.props.Document.childDropAction) as dropActionType, //onClick: undefined, // this.props.onClick, // bcz: check this out -- I don't think we want to inherit click handlers, or we at least need a way to ignore them onClick: this.onChildClickHandler, diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 276a49570..503df10c2 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -5,7 +5,6 @@ import { InkField, InkData } from "../../../../new_fields/InkField"; import { List } from "../../../../new_fields/List"; import { SchemaHeaderField } from "../../../../new_fields/SchemaHeaderField"; import { Cast, NumCast, FieldValue, StrCast } from "../../../../new_fields/Types"; -import { CurrentUserUtils } from "../../../../server/authentication/models/current_user_utils"; import { Utils } from "../../../../Utils"; import { Docs, DocUtils } from "../../../documents/Documents"; import { SelectionManager } from "../../../util/SelectionManager"; diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 03b2a2297..bd54d64ff 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -7,7 +7,7 @@ import { AudioField, nullAudio } from "../../../new_fields/URLField"; import { DocExtendableComponent } from "../DocComponent"; import { makeInterface, createSchema } from "../../../new_fields/Schema"; import { documentSchema } from "../../../new_fields/documentSchemas"; -import { Utils, returnTrue, emptyFunction, returnOne, returnTransparent } from "../../../Utils"; +import { Utils, returnTrue, emptyFunction, returnOne, returnTransparent, returnFalse } from "../../../Utils"; import { runInAction, observable, reaction, IReactionDisposer, computed, action } from "mobx"; import { DateField } from "../../../new_fields/DateField"; import { SelectionManager } from "../../util/SelectionManager"; @@ -258,9 +258,15 @@ export class AudioBox extends DocExtendableComponent
-
Doc.linkFollowHighlight(la1)} diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index eaab4086c..356192797 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -89,14 +89,15 @@ export class CollectionFreeFormDocumentView extends DocComponent - {!this.props.fitToBox ? : + : boolean; pinToPres: (document: Doc) => void; dontRegisterView?: boolean; + rootSelected: () => boolean; } @observer diff --git a/src/client/views/nodes/DocumentBox.tsx b/src/client/views/nodes/DocumentBox.tsx index debe104d7..47118e758 100644 --- a/src/client/views/nodes/DocumentBox.tsx +++ b/src/client/views/nodes/DocumentBox.tsx @@ -122,6 +122,7 @@ export class DocumentBox extends DocAnnotatableComponent Opt; + makeLink?: () => Opt, // function to call when a link is made }> { @computed get layout(): string { TraceMobx(); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 1e02ab44e..42f5fb946 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -60,6 +60,7 @@ export interface DocumentViewProps { LayoutDoc?: () => Opt; LibraryPath: Doc[]; fitToBox?: boolean; + rootSelected: () => boolean; // whether the root of a template has been selected onClick?: ScriptField; onPointerDown?: ScriptField; onPointerUp?: ScriptField; @@ -277,7 +278,7 @@ export class DocumentView extends DocComponent(Docu this.dontDecorateSelection = this.props.Document.dontDecorateSelection && (!e.ctrlKey || e.button < 2); if (!e.nativeEvent.cancelBubble && !this.Document.ignoreClick && (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) { - e.stopPropagation(); + let stopPropagate = true; let preventDefault = true; this.props.bringToFront(this.props.Document); if (this._doubleTap && this.props.renderDepth && !this.onClickHandler?.script) { // disable double-click to show full screen for things that have an on click behavior since clicking them twice can be misinterpreted as a double click @@ -301,9 +302,14 @@ export class DocumentView extends DocComponent(Docu SelectionManager.SelectDoc(this, e.ctrlKey); // don't think this should happen if a button action is actually triggered. UndoManager.RunInBatch(() => this.buttonClick(e.altKey, e.ctrlKey), "on link button follow"); } else { - SelectionManager.SelectDoc(this, e.ctrlKey); + if (this.props.Document.isTemplateForField && !(e.ctrlKey || e.button > 0)) { + stopPropagate = false; + } else { + SelectionManager.SelectDoc(this, e.ctrlKey); + } preventDefault = false; } + stopPropagate && e.stopPropagation(); preventDefault && e.preventDefault(); } } @@ -928,6 +934,9 @@ export class DocumentView extends DocComponent(Docu const fallback = Cast(this.props.Document.layoutKey, "string"); return typeof fallback === "string" ? fallback : "layout"; } + rootSelected = () => { + return this.isSelected(false) || (this.props.Document.forceActive && this.props.rootSelected?.() ? true : false); + } childScaling = () => (this.layoutDoc._fitWidth ? this.props.PanelWidth() / this.nativeWidth : this.props.ContentScaling()); @computed get contents() { TraceMobx(); @@ -937,6 +946,7 @@ export class DocumentView extends DocComponent(Docu DataDoc={this.props.DataDoc} LayoutDoc={this.props.LayoutDoc} makeLink={this.makeLink} + rootSelected={this.rootSelected} fitToBox={this.props.fitToBox} LibraryPath={this.props.LibraryPath} addDocument={this.props.addDocument} @@ -985,9 +995,13 @@ export class DocumentView extends DocComponent(Docu {StrCast(this.props.Document.title)} {this.Document.links && DocListCast(this.Document.links).filter(d => !d.hidden).filter(this.isNonTemporalLink).map((d, i) =>
- doc.hidden = true)} /> + doc.hidden = true)} />
)}
; } diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 0305f43d5..13a1becf7 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -29,6 +29,7 @@ export interface FieldViewProps { dropAction: dropActionType; isSelected: (outsideReaction?: boolean) => boolean; select: (isCtrlPressed: boolean) => void; + rootSelected: () => boolean; renderDepth: number; addDocument?: (document: Doc) => boolean; addDocTab: (document: Doc, where: string) => boolean; diff --git a/src/client/views/nodes/FormattedTextBoxComment.tsx b/src/client/views/nodes/FormattedTextBoxComment.tsx index 61df188f8..d1a563494 100644 --- a/src/client/views/nodes/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/FormattedTextBoxComment.tsx @@ -181,6 +181,7 @@ export class FormattedTextBoxComment { LibraryPath={emptyPath} fitToBox={true} moveDocument={returnFalse} + rootSelected={returnFalse} getTransform={Transform.Identity} active={returnFalse} addDocument={returnFalse} diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 71495d95f..c032f019d 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -31,8 +31,6 @@ import { InkingControl } from "../InkingControl"; import { InkTool } from "../../../new_fields/InkField"; import { TraceMobx } from "../../../new_fields/util"; import { PdfField } from "../../../new_fields/URLField"; -import { PDFBox } from "../nodes/PDFBox"; -import { FormattedTextBox } from "../nodes/FormattedTextBox"; import { DocumentView } from "../nodes/DocumentView"; const PDFJSViewer = require("pdfjs-dist/web/pdf_viewer"); const pdfjsLib = require("pdfjs-dist"); @@ -61,6 +59,7 @@ interface IViewerProps { PanelHeight: () => number; ContentScaling: () => number; select: (isCtrlPressed: boolean) => void; + rootSelected: () => boolean; startupLive: boolean; renderDepth: number; focus: (doc: Doc) => void; diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index 758795ed5..7ad3474e8 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -9,7 +9,7 @@ import { documentSchema } from '../../../new_fields/documentSchemas'; import { Id } from "../../../new_fields/FieldSymbols"; import { createSchema, makeInterface } from '../../../new_fields/Schema'; import { Cast, NumCast } from "../../../new_fields/Types"; -import { emptyFunction, emptyPath, returnFalse } from "../../../Utils"; +import { emptyFunction, emptyPath, returnFalse, returnTrue } from "../../../Utils"; import { Transform } from "../../util/Transform"; import { CollectionViewType } from '../collections/CollectionView'; import { DocExtendableComponent } from '../DocComponent'; @@ -175,6 +175,7 @@ export class PresElementBox extends DocExtendableComponent { Date: Fri, 3 Apr 2020 20:29:54 -0400 Subject: from last --- src/server/authentication/models/current_user_utils.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 7fe623f18..5b49e3c2d 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -251,9 +251,7 @@ export class CurrentUserUtils { return Docs.Create.ButtonDocument({ _width: 50, _height: 25, title: "Search", fontSize: 10, dontDecorateSelection: true, letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)", - sourcePanel: Docs.Create.QueryDocument({ - title: "search stack", - }), + sourcePanel: Docs.Create.QueryDocument({ title: "search stack", }), targetContainer: sidebarContainer, lockedPosition: true, onClick: ScriptField.MakeScript("this.targetContainer.proto = this.sourcePanel") @@ -283,9 +281,9 @@ export class CurrentUserUtils { const queryTemplate = Docs.Create.MultirowDocument( [ Docs.Create.QueryDocument({ title: "query", _height: 200 }), - Docs.Create.FreeformDocument([], { title: "data", _height: 100, _LODdisable: true }) + Docs.Create.FreeformDocument([], { title: "data", _height: 100, _LODdisable: true, forceActive: true}) ], - { _width: 400, _height: 300, title: "queryView", _chromeStatus: "disabled", _xMargin: 3, _yMargin: 3, _autoHeight: false }); + { _width: 400, _height: 300, title: "queryView", _chromeStatus: "disabled", _xMargin: 3, _yMargin: 3, _autoHeight: false, forceActive: true }); queryTemplate.isTemplateDoc = makeTemplate(queryTemplate); const slideTemplate = Docs.Create.MultirowDocument( [ -- cgit v1.2.3-70-g09d2 From 3949f6a094f835e495562ab5484b23ade3d1003f Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Fri, 3 Apr 2020 17:37:36 -0700 Subject: restored session manager content, things compile and seem to run fine --- src/server/ApiManagers/SessionManager.ts | 20 ++++++++++---------- src/server/index.ts | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/server/ApiManagers/SessionManager.ts b/src/server/ApiManagers/SessionManager.ts index c993c985f..bcaa6598f 100644 --- a/src/server/ApiManagers/SessionManager.ts +++ b/src/server/ApiManagers/SessionManager.ts @@ -2,7 +2,7 @@ import ApiManager, { Registration } from "./ApiManager"; import { Method, _permission_denied, AuthorizedCore, SecureHandler } from "../RouteManager"; import RouteSubscriber from "../RouteSubscriber"; import { sessionAgent } from ".."; -// import { DashSessionAgent } from "../DashSession/DashSessionAgent"; +import { DashSessionAgent } from "../DashSession/DashSessionAgent"; const permissionError = "You are not authorized!"; @@ -25,15 +25,15 @@ export default class SessionManager extends ApiManager { protected initialize(register: Registration): void { - // register({ - // method: Method.GET, - // subscription: this.secureSubscriber("debug", "to?"), - // secureHandler: this.authorizedAction(async ({ req: { params }, res }) => { - // const to = params.to || DashSessionAgent.notificationRecipient; - // const { error } = await sessionAgent.serverWorker.emit("debug", { to }); - // res.send(error ? error.message : `Your request was successful: the server captured and compressed (but did not save) a new back up. It was sent to ${to}.`); - // }) - // }); + register({ + method: Method.GET, + subscription: this.secureSubscriber("debug", "to?"), + secureHandler: this.authorizedAction(async ({ req: { params }, res }) => { + const to = params.to || DashSessionAgent.notificationRecipient; + const { error } = await sessionAgent.serverWorker.emit("debug", { to }); + res.send(error ? error.message : `Your request was successful: the server captured and compressed (but did not save) a new back up. It was sent to ${to}.`); + }) + }); register({ method: Method.GET, diff --git a/src/server/index.ts b/src/server/index.ts index 8325f5d44..97f70630b 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -22,7 +22,7 @@ import GeneralGoogleManager from "./ApiManagers/GeneralGoogleManager"; import GooglePhotosManager from "./ApiManagers/GooglePhotosManager"; import { Logger } from "./ProcessFactory"; import { yellow } from "colors"; -// import { DashSessionAgent } from "./DashSession/DashSessionAgent"; +import { DashSessionAgent } from "./DashSession/DashSessionAgent"; import SessionManager from "./ApiManagers/SessionManager"; import { AppliedSessionAgent } from "./DashSession/Session/agents/applied_session_agent"; import { Utils } from "../Utils"; @@ -146,7 +146,7 @@ export async function launchServer() { * So, the 'else' clause is exactly what we've always run when executing npm start. */ if (process.env.RELEASE) { - // (sessionAgent = new DashSessionAgent()).launch(); + (sessionAgent = new DashSessionAgent()).launch(); } else { launchServer(); } -- cgit v1.2.3-70-g09d2 From 0a6def774881f8b0c4164b8638e3f266f232ff07 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 3 Apr 2020 21:53:05 -0400 Subject: fixed queryView template a bit. --- src/client/documents/Documents.ts | 1 + src/client/views/collections/CollectionView.tsx | 2 +- src/client/views/nodes/QueryBox.tsx | 2 +- src/client/views/search/SearchBox.scss | 2 +- src/server/authentication/models/current_user_utils.ts | 8 ++++---- 5 files changed, 8 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 0a2269bac..c5b080ffb 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -103,6 +103,7 @@ export interface DocumentOptions { isDisplayPanel?: boolean; // whether the panel functions as GoldenLayout "stack" used to display documents forceActive?: boolean; layout?: string | Doc; + hideFilterView?: boolean; // whether to hide the filter popout on collections hideHeadings?: boolean; // whether stacking view column headings should be hidden isTemplateForField?: string; // the field key for which the containing document is a rendering template isTemplateDoc?: boolean; diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 3913ccd88..23d701ffd 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -463,7 +463,7 @@ export class CollectionView extends Touchable { Utils.CorsProxy(Cast(d.data, ImageField)!.url.href) : Cast(d.data, ImageField)!.url.href : ""))} - {!this.props.isSelected() || this.props.PanelHeight() < 100 ? (null) : + {!this.props.isSelected() || this.props.PanelHeight() < 100 || this.props.Document.hideFilterView ? (null) :
diff --git a/src/client/views/nodes/QueryBox.tsx b/src/client/views/nodes/QueryBox.tsx index 566c07dfe..7016b4f04 100644 --- a/src/client/views/nodes/QueryBox.tsx +++ b/src/client/views/nodes/QueryBox.tsx @@ -27,7 +27,7 @@ export class QueryBox extends DocAnnotatableComponent + return
e.stopPropagation()} >
; } diff --git a/src/client/views/search/SearchBox.scss b/src/client/views/search/SearchBox.scss index ec4eda643..f0223ca76 100644 --- a/src/client/views/search/SearchBox.scss +++ b/src/client/views/search/SearchBox.scss @@ -9,7 +9,7 @@ position: absolute; font-size: 10px; line-height: 1; - overflow: hidden; + overflow: auto; background: lightgrey, } diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 5b49e3c2d..e34a9b958 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -251,7 +251,7 @@ export class CurrentUserUtils { return Docs.Create.ButtonDocument({ _width: 50, _height: 25, title: "Search", fontSize: 10, dontDecorateSelection: true, letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)", - sourcePanel: Docs.Create.QueryDocument({ title: "search stack", }), + sourcePanel: Docs.Create.QueryDocument({ title: "search stack", }), targetContainer: sidebarContainer, lockedPosition: true, onClick: ScriptField.MakeScript("this.targetContainer.proto = this.sourcePanel") @@ -278,12 +278,12 @@ export class CurrentUserUtils { /// sets up the default list of buttons to be shown in the expanding button menu at the bottom of the Dash window static setupExpandingButtons(doc: Doc) { - const queryTemplate = Docs.Create.MultirowDocument( + const queryTemplate = Docs.Create.MulticolumnDocument( [ Docs.Create.QueryDocument({ title: "query", _height: 200 }), - Docs.Create.FreeformDocument([], { title: "data", _height: 100, _LODdisable: true, forceActive: true}) + Docs.Create.FreeformDocument([], { title: "data", _height: 100, _LODdisable: true, forceActive: true }) ], - { _width: 400, _height: 300, title: "queryView", _chromeStatus: "disabled", _xMargin: 3, _yMargin: 3, _autoHeight: false, forceActive: true }); + { _width: 400, _height: 300, title: "queryView", _chromeStatus: "disabled", _xMargin: 3, _yMargin: 3, _autoHeight: false, forceActive: true, hideFilterView: true }); queryTemplate.isTemplateDoc = makeTemplate(queryTemplate); const slideTemplate = Docs.Create.MultirowDocument( [ -- cgit v1.2.3-70-g09d2 From fac740378a9eeaeb0af4567f6402120aba8bd62e Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 3 Apr 2020 22:04:19 -0400 Subject: cleaning up .. removing Docs.Create.SearchDocument --- src/client/documents/DocumentTypes.ts | 2 +- src/client/documents/Documents.ts | 4 --- src/client/views/SearchDocBox.tsx | 37 ++++++++-------------- src/client/views/nodes/DocumentContentsView.tsx | 1 - src/client/views/search/SearchBox.tsx | 3 -- .../authentication/models/current_user_utils.ts | 2 +- 6 files changed, 15 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index 5ec1cfdb4..b98e4d581 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -22,7 +22,7 @@ export enum DocumentType { RECOMMENDATION = "recommendation", LINKFOLLOW = "linkfollow", PRESELEMENT = "preselement", - QUERY = "search", + QUERY = "query", COLOR = "color", DOCULINK = "doculink", PDFANNO = "pdfanno", diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index c5b080ffb..1a2969cf5 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -708,10 +708,6 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.RECOMMENDATION), new List(data), options); } - export function SearchDocument(documents: Array, options: DocumentOptions = {}) { - return InstanceFromProto(Prototypes.get(DocumentType.SEARCHBOX), new List(documents), options); - } - export type DocConfig = { doc: Doc, initialWidth?: number, diff --git a/src/client/views/SearchDocBox.tsx b/src/client/views/SearchDocBox.tsx index e66de39d4..cd9666af8 100644 --- a/src/client/views/SearchDocBox.tsx +++ b/src/client/views/SearchDocBox.tsx @@ -1,31 +1,20 @@ +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 React = require("react"); -import { observable, action, computed, runInAction } from "mobx"; -import Measure from "react-measure"; //import "./SearchBoxDoc.scss"; -import { Doc, DocListCast, WidthSym, HeightSym } from "../../new_fields/Doc"; -import { DocumentIcon } from "./nodes/DocumentIcon"; -import { StrCast, NumCast, BoolCast, Cast } from "../../new_fields/Types"; -import { returnFalse, emptyFunction, returnEmptyString, returnOne } from "../../Utils"; -import { Transform } from "../util/Transform"; -import { ObjectField } from "../../new_fields/ObjectField"; -import { DocumentView } from "./nodes/DocumentView"; -import { DocumentType } from '../documents/DocumentTypes'; -import { ClientRecommender } from "../ClientRecommender"; -import { DocServer } from "../DocServer"; +import { Doc, DocListCast } from "../../new_fields/Doc"; import { Id } from "../../new_fields/FieldSymbols"; -import { FieldView, FieldViewProps } from "./nodes/FieldView"; -import { DocumentManager } from "../util/DocumentManager"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { library } from "@fortawesome/fontawesome-svg-core"; -import { faBullseye, faLink } from "@fortawesome/free-solid-svg-icons"; -import { DocUtils, Docs } from "../documents/Documents"; -import { ContentFittingDocumentView } from "./nodes/ContentFittingDocumentView"; -import { EditableView } from "./EditableView"; +import { BoolCast, Cast, NumCast, StrCast } from "../../new_fields/Types"; +import { returnFalse } from "../../Utils"; +import { Docs } from "../documents/Documents"; import { SearchUtil } from "../util/SearchUtil"; -import { SearchItem } from "./search/SearchItem"; +import { EditableView } from "./EditableView"; +import { ContentFittingDocumentView } from "./nodes/ContentFittingDocumentView"; +import { FieldView, FieldViewProps } from "./nodes/FieldView"; import { FilterBox } from "./search/FilterBox"; -import { SearchBox } from "./search/SearchBox"; +import { SearchItem } from "./search/SearchItem"; +import React = require("react"); export interface RecProps { documents: { preview: Doc, similarity: number }[]; @@ -301,7 +290,7 @@ export class SearchDocBox extends React.Component { } } //return Docs.Create.TreeDocument(docs, { _width: 200, _height: 400, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` }); - return Docs.Create.SearchDocument(docs, { _width: 200, _height: 400, searchText: this._searchString, title: `Search Docs: "${this._searchString}"` }); + return Docs.Create.QueryDocument(docs, { _width: 200, _height: 400, searchText: this._searchString, title: `Query Docs: "${this._searchString}"` }); } @action.bound diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 687137adc..dc71ba280 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -35,7 +35,6 @@ import { WebBox } from "./WebBox"; import { InkingStroke } from "../InkingStroke"; import React = require("react"); import { RecommendationsBox } from "../RecommendationsBox"; -import { SearchBox } from "../search/SearchBox"; import { TraceMobx } from "../../../new_fields/util"; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index e7941a9ba..49b6b18ca 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -416,9 +416,6 @@ export class SearchBox extends React.Component { y += 300; } } - console.log("create"); - //return Docs.Create.TreeDocument(docs, { _width: 200, _height: 400, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` }); - //return Docs.Create.SearchDocument(docs, { _width: 200, _height: 400, searchText: this._searchString, title: `Search Docs: "${this._searchString}"` }); return Docs.Create.QueryDocument({ _autoHeight: true, title: this._searchString, filterQuery: this.filterQuery, searchQuery: this._searchString }); } diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index e34a9b958..fc6e36485 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -89,7 +89,7 @@ export class CurrentUserUtils { { title: "use stamp", icon: "stamp", click: 'activateStamp(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this)', backgroundColor: "orange", ischecked: `sameDocs(this.activePen.pen, this)`, activePen: doc }, { title: "use eraser", icon: "eraser", click: 'activateEraser(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this);', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "pink", activePen: doc }, { title: "use drag", icon: "mouse-pointer", click: 'deactivateInk();this.activePen.pen = this;', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "white", activePen: doc }, - { title: "search", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.SearchDocument({ _width: 200, title: "an image of a cat" })' }, + { title: "query", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.QueryDocument({ _width: 200, title: "an image of a cat" })' }, ]; -- cgit v1.2.3-70-g09d2