From c3d4b851d81d42256b972a6b8eaa9c9210232953 Mon Sep 17 00:00:00 2001 From: monikahedman Date: Sat, 6 Jul 2019 14:52:53 -0400 Subject: free cookies! --- src/client/views/search/SearchBox.tsx | 77 +++++++++++++++++++++++++++++---- src/client/views/search/SearchItem.scss | 41 ++++++++++++------ 2 files changed, 96 insertions(+), 22 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 1f6835c26..327f9514a 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -26,6 +26,12 @@ export class SearchBox extends React.Component { @observable public _pageNum: number = 0; //temp @observable public _maxNum: number = 10; + @observable private _visibleElements: JSX.Element[] = []; + @observable private _scrollY: number = 0; + + private _isSearch: ("search" | "placeholder" | undefined)[] = []; + private _currentIndex = 0; + private _numResults = 0; static Instance: SearchBox; @@ -90,25 +96,35 @@ export class SearchBox extends React.Component { else { //gets json result into a list of documents that can be used //these are filtered by type - results = await this.getResults(query); + this._currentIndex = 0; + results = await this.getResults(query, 12); } runInAction(() => { this._resultsOpen = true; this._results = results; this._openNoResults = true; + this.resultsScrolled(); }); } @action - getResults = async (query: string) => { - const { docs } = await SearchUtil.Search(query, true); - return FilterBox.Instance.filterDocsByType(docs); + getResults = async (query: string, count: number) => { + let resDocs = []; + while (resDocs.length < count) { + const { docs, numFound } = await SearchUtil.Search(query, true, count === -1 ? undefined : this._currentIndex, count === -1 ? undefined : this._maxNum); + if (numFound !== this._numResults) { + this._numResults = numFound; + } + resDocs.push(...FilterBox.Instance.filterDocsByType(docs)); + this._currentIndex += this._maxNum; + } + return resDocs; } collectionRef = React.createRef(); startDragCollection = async () => { - const results = await this.getResults(FilterBox.Instance.getFinalQuery(this._searchString)); + const results = await this.getResults(FilterBox.Instance.getFinalQuery(this._searchString), -1); const docs = results.map(doc => { const isProto = Doc.GetT(doc, "isPrototype", "boolean", true); if (isProto) { @@ -166,6 +182,50 @@ export class SearchBox extends React.Component { this._results = []; } + resultsScrolled = async (e?: React.UIEvent) => { + let scrollY = e ? e.currentTarget.scrollTop : 0; + let buffer = 4; + let startIndex = Math.floor(Math.max(0, scrollY / 70 - buffer)); + let endIndex = Math.ceil(Math.min(this._numResults - 1, startIndex + (560 / 70) + buffer)); + + runInAction(() => { + if (this._numResults === 0 && this._openNoResults) { + this._visibleElements = [
No Search Results
]; + return; + } + else if (this._visibleElements.length !== this._numResults) { + this._visibleElements = Array(this._numResults); + this._isSearch = Array(this._numResults); + } + }); + + for (let i = 0; i < this._numResults; i++) { + if (i < startIndex || i > endIndex) { + if (this._isSearch[i] !== "placeholder") { + this._isSearch[i] = "placeholder"; + runInAction(() => { + this._visibleElements[i] =
; + }); + } + } + else { + if (this._isSearch[i] !== "search") { + let result: Doc | undefined = undefined; + if (i >= this._results.length) { + this._results.push(...(await this.getResults(this._searchString, 1))); + } + result = this._results[i]; + if (result) { + runInAction(() => { + this._visibleElements[i] = ; + }); + this._isSearch[i] = "search"; + } + } + } + } + } + render() { return (
@@ -178,11 +238,12 @@ export class SearchBox extends React.Component { style={{ width: this._resultsOpen ? "500px" : "100px" }} />
-
- {(this._results.length !== 0) ? ( +
+ {/* {(this._results.length !== 0) ? ( this._results.map(result => ) ) : - this._openNoResults ? (
No Search Results
) : null} + this._openNoResults ? (
No Search Results
) : null} */} + {this._visibleElements}
{/*
diff --git a/src/client/views/search/SearchItem.scss b/src/client/views/search/SearchItem.scss index fa4c9cb38..c384e3bfc 100644 --- a/src/client/views/search/SearchItem.scss +++ b/src/client/views/search/SearchItem.scss @@ -86,21 +86,24 @@ .link-container.item:hover .link-extended { opacity: 1; } - + .icon-icons { - width:50px + width: 50px } + .icon-live { - width:175px; + width: 175px; } - .icon-icons, .icon-live { - height:50px; - margin:auto; + .icon-icons, + .icon-live { + height: 50px; + margin: auto; overflow: hidden; + .search-type { display: inline-block; - width:100%; + width: 100%; position: absolute; justify-content: center; align-items: center; @@ -112,10 +115,11 @@ overflow: hidden; img { - width:100% !important; - height:auto !important; + width: 100% !important; + height: auto !important; } } + .search-type:hover+.search-label { opacity: 1; } @@ -134,16 +138,18 @@ } .icon-live:hover { - height:175px; + height: 175px; + .pdfBox-cont { img { - width:100% !important; + width: 100% !important; } } } } + .search-info:hover { - width:60%; + width: 60%; } } } @@ -176,12 +182,19 @@ } } + .search-overview:hover { z-index: 1; } + +.searchBox-placeholder { + min-height: 70px; +} + .collection { - display:flex; + display: flex; } + .collection-item { - width:35px; + width: 35px; } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 6cc2335bc6d318ec780bdaecfbad4e047a7b5ac9 Mon Sep 17 00:00:00 2001 From: monikahedman Date: Mon, 8 Jul 2019 18:49:40 -0400 Subject: end of day 7/8 --- src/client/views/pdf/PDFMenu.tsx | 12 ++-- src/client/views/search/FilterBox.tsx | 2 +- src/client/views/search/SearchBox.tsx | 115 +++++++++++++++++++++++----------- 3 files changed, 86 insertions(+), 43 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx index f93b2e59f..b979a9932 100644 --- a/src/client/views/pdf/PDFMenu.tsx +++ b/src/client/views/pdf/PDFMenu.tsx @@ -242,24 +242,24 @@ export default class PDFMenu extends React.Component { render() { let buttons = this.Status === "pdf" || this.Status === "snippet" ? [ - , - , + , this.Status === "snippet" ? : undefined, - ] : [ - , - , + , + ,
, - , + , ]; return ( diff --git a/src/client/views/search/FilterBox.tsx b/src/client/views/search/FilterBox.tsx index 23a1b31d8..4c74c0413 100644 --- a/src/client/views/search/FilterBox.tsx +++ b/src/client/views/search/FilterBox.tsx @@ -242,7 +242,7 @@ export class FilterBox extends React.Component { let finalDocs: Doc[] = []; docs.forEach(doc => { let layoutresult = Cast(doc.type, "string"); - if (!layoutresult || this._icons.includes(layoutresult)) { + if (layoutresult && this._icons.includes(layoutresult)) { finalDocs.push(doc); } }); diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 327f9514a..430ca3b2e 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -15,6 +15,7 @@ import { Id } from '../../../new_fields/FieldSymbols'; import { SearchUtil } from '../../util/SearchUtil'; import { RouteStore } from '../../../server/RouteStore'; import { FilterBox } from './FilterBox'; +import { start } from 'repl'; @observer export class SearchBox extends React.Component { @@ -31,7 +32,10 @@ export class SearchBox extends React.Component { private _isSearch: ("search" | "placeholder" | undefined)[] = []; private _currentIndex = 0; - private _numResults = 0; + private _numTotalResults = 0; + private _numFilteredResults = 0; + private _startIndex = -1; + private _endIndex = -1; static Instance: SearchBox; @@ -55,15 +59,16 @@ export class SearchBox extends React.Component { onChange(e: React.ChangeEvent) { this._searchString = e.target.value; - if (this._searchString === "") { - this._results = []; - this._openNoResults = false; - } + this._openNoResults = false; + this._results = []; + this._visibleElements = []; + this._currentIndex = 0; + this._numTotalResults = 0; + this._startIndex = -1; + this._endIndex = -1; } - enter = (e: React.KeyboardEvent) => { - if (e.key === "Enter") { this.submitSearch(); } - } + enter = (e: React.KeyboardEvent) => { if (e.key === "Enter") { this.submitSearch(); } } public static async convertDataUri(imageUri: string, returnedFilename: string) { try { @@ -111,13 +116,30 @@ export class SearchBox extends React.Component { @action getResults = async (query: string, count: number) => { let resDocs = []; + // count is total number of documents to be shown (i believe) + console.log(`Count: ${count}`); while (resDocs.length < count) { - const { docs, numFound } = await SearchUtil.Search(query, true, count === -1 ? undefined : this._currentIndex, count === -1 ? undefined : this._maxNum); - if (numFound !== this._numResults) { - this._numResults = numFound; + let index = count === -1 ? undefined : this._currentIndex; + let num = count === -1 ? undefined : Math.min(this._numTotalResults - this._currentIndex + 1, this._maxNum); + // num found has to be the number of docs before filtering happens - this is the total num + const { docs, numFound } = await SearchUtil.Search(query, true, index, num); + // accounts for the fact that there may be fewer documents than the max that are returned + let filteredDocs = FilterBox.Instance.filterDocsByType(docs); + count = Math.min(numFound, count); + // uh what is going on here with the first part? + if (numFound !== this._numTotalResults && this._numTotalResults === 0) { + console.log(`Total: ${numFound}`); + this._numTotalResults = numFound; } - resDocs.push(...FilterBox.Instance.filterDocsByType(docs)); - this._currentIndex += this._maxNum; + + // if (filteredDocs.length < docs.length) { + // this._numResults -= docs.length - filteredDocs.length; + // console.log(`New Total: ${this._numResults}`); + // } + resDocs.push(...filteredDocs); + this._currentIndex += docs.length; + console.log(`ResDocs: ${resDocs.length}`); + console.log(`CurrIndex: ${this._currentIndex}`); } return resDocs; } @@ -171,7 +193,7 @@ export class SearchBox extends React.Component { @action.bound closeSearch = () => { - console.log("closing search"); + console.log("closing search") FilterBox.Instance.closeFilter(); this.closeResults(); } @@ -180,46 +202,67 @@ export class SearchBox extends React.Component { closeResults() { this._resultsOpen = false; this._results = []; + this._visibleElements = []; + this._currentIndex = 0; + this._numTotalResults = 0; + this._startIndex = -1; + this._endIndex = -1; } + @action resultsScrolled = async (e?: React.UIEvent) => { let scrollY = e ? e.currentTarget.scrollTop : 0; let buffer = 4; let startIndex = Math.floor(Math.max(0, scrollY / 70 - buffer)); - let endIndex = Math.ceil(Math.min(this._numResults - 1, startIndex + (560 / 70) + buffer)); + let endIndex = Math.ceil(Math.min(this._numTotalResults - 1, startIndex + (560 / 70) + buffer)); - runInAction(() => { - if (this._numResults === 0 && this._openNoResults) { - this._visibleElements = [
No Search Results
]; - return; - } - else if (this._visibleElements.length !== this._numResults) { - this._visibleElements = Array(this._numResults); - this._isSearch = Array(this._numResults); - } - }); + if (startIndex === this._startIndex && endIndex === this._endIndex) { + return; + } + + console.log(`START: ${startIndex}`); + console.log(`END: ${endIndex}`); + + this._startIndex = startIndex; + this._endIndex = endIndex; + + if (this._numTotalResults === 0 && this._openNoResults) { + this._visibleElements = [
No Search Results
]; + return; + } - for (let i = 0; i < this._numResults; i++) { + else if (this._visibleElements.length !== this._numTotalResults) { + this._visibleElements = Array(this._numTotalResults); + this._isSearch = Array(this._numTotalResults); + } + + for (let i = 0; i < this._numTotalResults; i++) { if (i < startIndex || i > endIndex) { if (this._isSearch[i] !== "placeholder") { this._isSearch[i] = "placeholder"; - runInAction(() => { - this._visibleElements[i] =
; - }); + this._visibleElements[i] =
; } } else { if (this._isSearch[i] !== "search") { let result: Doc | undefined = undefined; if (i >= this._results.length) { - this._results.push(...(await this.getResults(this._searchString, 1))); - } - result = this._results[i]; - if (result) { + let results = await this.getResults(this._searchString, i - this._results.length) runInAction(() => { - this._visibleElements[i] = ; - }); - this._isSearch[i] = "search"; + this._results.push(...results); + result = this._results[i]; + if (result) { + this._visibleElements[i] = ; + this._isSearch[i] = "search"; + } + }) + } + else { + result = this._results[i]; + if (result) { + this._visibleElements[i] = ; + this._isSearch[i] = "search"; + } } } } -- cgit v1.2.3-70-g09d2 From 701509141f793d4c7335771ade8a7b1dae49985a Mon Sep 17 00:00:00 2001 From: monikahedman Date: Wed, 10 Jul 2019 16:14:13 -0400 Subject: bout to do something cray --- src/client/views/search/SearchBox.tsx | 137 ++++++++++++++++++++++++++++++---- 1 file changed, 121 insertions(+), 16 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 430ca3b2e..296d2ccc8 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { observer } from 'mobx-react'; -import { observable, action, runInAction } from 'mobx'; +import { observable, action, runInAction, flow } from 'mobx'; import "./SearchBox.scss"; import "./FilterBox.scss"; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; @@ -33,9 +33,9 @@ export class SearchBox extends React.Component { private _isSearch: ("search" | "placeholder" | undefined)[] = []; private _currentIndex = 0; private _numTotalResults = 0; - private _numFilteredResults = 0; private _startIndex = -1; private _endIndex = -1; + private _fetchedIndices: number[] = [0]; static Instance: SearchBox; @@ -43,6 +43,7 @@ export class SearchBox extends React.Component { super(props); SearchBox.Instance = this; + this.resultsScrolled = this.resultsScrolled.bind(this); } @action @@ -123,10 +124,13 @@ export class SearchBox extends React.Component { let num = count === -1 ? undefined : Math.min(this._numTotalResults - this._currentIndex + 1, this._maxNum); // num found has to be the number of docs before filtering happens - this is the total num const { docs, numFound } = await SearchUtil.Search(query, true, index, num); - // accounts for the fact that there may be fewer documents than the max that are returned + let filteredDocs = FilterBox.Instance.filterDocsByType(docs); + + // accounts for the fact that there may be fewer documents than the max that are returned count = Math.min(numFound, count); - // uh what is going on here with the first part? + + // happens at the beginning if (numFound !== this._numTotalResults && this._numTotalResults === 0) { console.log(`Total: ${numFound}`); this._numTotalResults = numFound; @@ -137,13 +141,104 @@ export class SearchBox extends React.Component { // console.log(`New Total: ${this._numResults}`); // } resDocs.push(...filteredDocs); + this._currentIndex += docs.length; + console.log(`ResDocs: ${resDocs.length}`); console.log(`CurrIndex: ${this._currentIndex}`); } + console.log(this.getResults2(query, count, [])); return resDocs; } + @action + getResults2 = async (query: string, count: number, docs?: Doc[]) => { + console.log("results 2") + let buffer = 4; + // let goalIndex = this._endIndex + count; + // let bottomBound = Math.floor(goalIndex / 10) * 10; + let tempIndex = this._currentIndex; + let goalNum = this._endIndex + buffer; + let resDocs: Doc[]; + + if (docs) { + resDocs = docs; + } else { + resDocs = []; + } + + // let topBound = bottomBound - 10; + // let unfilteredDocs: Doc[]; + // let unfilteredFound: number; + // means this has already been fetched + // if (this._fetchedIndices.includes(topBound)) { + // return; + // } + + let index = count <= 0 ? undefined : this._currentIndex; + if (index) { + let topBound = Math.ceil(index / 10) * 10; + if (this._fetchedIndices.includes(topBound)) { + return; + } + let startIndex = this._fetchedIndices[this._fetchedIndices.length - 1]; + let endIndex = startIndex + 10; + this._fetchedIndices.push(endIndex); + console.log(this._fetchedIndices) + let prom: Promise = SearchUtil.Search(query, true, index, 10); + + prom.then((res: SearchUtil.DocSearchResult) => { + count = Math.min(res.numFound, count); + console.log(res.docs); + let filteredDocs = FilterBox.Instance.filterDocsByType(res.docs); + + if (res.numFound !== this._numTotalResults && this._numTotalResults === 0) { + this._numTotalResults = res.numFound; + } + + resDocs.push(...filteredDocs); + + tempIndex += res.docs.length; + + if (filteredDocs.length <= count) { + runInAction(() => { + return this.getResults2(query, count - filteredDocs.length, resDocs); + }); + } + else { + return resDocs; + } + console.log(tempIndex); + console.log(resDocs.length); + }) + + } + //this is the upper bound of the last + // let index = this._fetchedIndices[this._fetchedIndices.length - 1]; + // let prom: Promise = SearchUtil.Search(query, true, index, 10); + + // prom.then((res: SearchUtil.DocSearchResult) => { + // // unfilteredDocs = res.docs; + // // unfilteredFound = res.numFound; + + // count = Math.min(res.numFound, count); + // let filteredDocs = FilterBox.Instance.filterDocsByType(res.docs); + + // if (res.numFound !== this._numTotalResults && this._numTotalResults === 0) { + // console.log(`Total: ${res.numFound}`); + // this._numTotalResults = res.numFound; + // } + + // resDocs.push(...filteredDocs); + + // this._currentIndex += res.docs.length; + // }) + + // console.log(prom); + + + } + collectionRef = React.createRef(); startDragCollection = async () => { const results = await this.getResults(FilterBox.Instance.getFinalQuery(this._searchString), -1); @@ -209,8 +304,7 @@ export class SearchBox extends React.Component { this._endIndex = -1; } - @action - resultsScrolled = async (e?: React.UIEvent) => { + resultsScrolled = flow(function* (this: SearchBox, e?: React.UIEvent) { let scrollY = e ? e.currentTarget.scrollTop : 0; let buffer = 4; let startIndex = Math.floor(Math.max(0, scrollY / 70 - buffer)); @@ -222,6 +316,7 @@ export class SearchBox extends React.Component { console.log(`START: ${startIndex}`); console.log(`END: ${endIndex}`); + console.log("_________________________________________________________________________________________________________") this._startIndex = startIndex; this._endIndex = endIndex; @@ -231,12 +326,18 @@ export class SearchBox extends React.Component { return; } + // 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); + // indicates if things are placeholders this._isSearch = Array(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"; @@ -247,15 +348,19 @@ export class SearchBox extends React.Component { if (this._isSearch[i] !== "search") { let result: Doc | undefined = undefined; if (i >= this._results.length) { - let results = await this.getResults(this._searchString, i - this._results.length) - runInAction(() => { - this._results.push(...results); - result = this._results[i]; - if (result) { - this._visibleElements[i] = ; - this._isSearch[i] = "search"; - } - }) + // _________________________________________________________________________________________________ + let results: Doc[] = yield this.getResults(this._searchString, i + 1 - this._results.length); + if (results.length !== 0) { + runInAction(() => { + this._results.push(...results); + result = this._results[i]; + if (result) { + this._visibleElements[i] = ; + this._isSearch[i] = "search"; + } + }); + } + // _________________________________________________________________________________________________ } else { result = this._results[i]; @@ -267,7 +372,7 @@ export class SearchBox extends React.Component { } } } - } + }); render() { return ( -- cgit v1.2.3-70-g09d2 From a2e762e4a85eca92401394afe7dbc03db5a5b473 Mon Sep 17 00:00:00 2001 From: monikahedman Date: Wed, 10 Jul 2019 18:17:14 -0400 Subject: hate this --- src/client/views/search/SearchBox.tsx | 55 +++++++++++++++-------------------- 1 file changed, 23 insertions(+), 32 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 296d2ccc8..db6f69ccb 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -65,8 +65,8 @@ export class SearchBox extends React.Component { this._visibleElements = []; this._currentIndex = 0; this._numTotalResults = 0; - this._startIndex = -1; - this._endIndex = -1; + this._startIndex = 0; + this._endIndex = 12; } enter = (e: React.KeyboardEvent) => { if (e.key === "Enter") { this.submitSearch(); } } @@ -144,28 +144,21 @@ export class SearchBox extends React.Component { this._currentIndex += docs.length; - console.log(`ResDocs: ${resDocs.length}`); + // console.log(`ResDocs: ${resDocs.length}`); console.log(`CurrIndex: ${this._currentIndex}`); } - console.log(this.getResults2(query, count, [])); + // console.log(this.getResults2(query, count, [])); return resDocs; } @action - getResults2 = async (query: string, count: number, docs?: Doc[]) => { - console.log("results 2") - let buffer = 4; + getResults2 = async (query: string, count: number, docs: Doc[]) => { + // let buffer = 4; // let goalIndex = this._endIndex + count; // let bottomBound = Math.floor(goalIndex / 10) * 10; - let tempIndex = this._currentIndex; - let goalNum = this._endIndex + buffer; - let resDocs: Doc[]; - - if (docs) { - resDocs = docs; - } else { - resDocs = []; - } + // let tempIndex = this._currentIndex; + // let goalNum = this._endIndex + buffer; + let resDocs: Doc[] = docs; // let topBound = bottomBound - 10; // let unfilteredDocs: Doc[]; @@ -176,10 +169,12 @@ export class SearchBox extends React.Component { // } let index = count <= 0 ? undefined : this._currentIndex; + // let index = this._currentIndex; if (index) { let topBound = Math.ceil(index / 10) * 10; if (this._fetchedIndices.includes(topBound)) { - return; + // console.log("returning NOTHING") + return resDocs; } let startIndex = this._fetchedIndices[this._fetchedIndices.length - 1]; let endIndex = startIndex + 10; @@ -198,21 +193,17 @@ export class SearchBox extends React.Component { resDocs.push(...filteredDocs); - tempIndex += res.docs.length; + this._currentIndex += res.docs.length; - if (filteredDocs.length <= count) { - runInAction(() => { - return this.getResults2(query, count - filteredDocs.length, resDocs); - }); - } - else { - return resDocs; + if (resDocs.length < count) { + return this.getResults2(query, count - resDocs.length, resDocs); + // resDocs = await this.getResults2(query, count - filteredDocs.length, resDocs); } - console.log(tempIndex); - console.log(resDocs.length); - }) + return resDocs; + }) } + return resDocs; //this is the upper bound of the last // let index = this._fetchedIndices[this._fetchedIndices.length - 1]; // let prom: Promise = SearchUtil.Search(query, true, index, 10); @@ -300,8 +291,8 @@ export class SearchBox extends React.Component { this._visibleElements = []; this._currentIndex = 0; this._numTotalResults = 0; - this._startIndex = -1; - this._endIndex = -1; + this._startIndex = 0; + this._endIndex = 12; } resultsScrolled = flow(function* (this: SearchBox, e?: React.UIEvent) { @@ -316,8 +307,6 @@ export class SearchBox extends React.Component { console.log(`START: ${startIndex}`); console.log(`END: ${endIndex}`); - console.log("_________________________________________________________________________________________________________") - this._startIndex = startIndex; this._endIndex = endIndex; @@ -350,6 +339,7 @@ export class SearchBox extends React.Component { if (i >= this._results.length) { // _________________________________________________________________________________________________ let results: Doc[] = yield this.getResults(this._searchString, i + 1 - this._results.length); + console.log(results) if (results.length !== 0) { runInAction(() => { this._results.push(...results); @@ -372,6 +362,7 @@ export class SearchBox extends React.Component { } } } + console.log("_________________________________________________________________________________________________________") }); render() { -- cgit v1.2.3-70-g09d2 From 8888e3aef8658e4100e2fc4bee6b805e7b0feaa9 Mon Sep 17 00:00:00 2001 From: monikahedman Date: Wed, 10 Jul 2019 20:31:57 -0400 Subject: dear god i hate this --- src/client/views/search/SearchBox.tsx | 173 +++++++++++++++++----------------- 1 file changed, 87 insertions(+), 86 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index db6f69ccb..1980ddaf2 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -39,6 +39,8 @@ export class SearchBox extends React.Component { static Instance: SearchBox; + private _maxSearchIndex: number = 0; + constructor(props: any) { super(props); @@ -65,8 +67,8 @@ export class SearchBox extends React.Component { this._visibleElements = []; this._currentIndex = 0; this._numTotalResults = 0; - this._startIndex = 0; - this._endIndex = 12; + this._startIndex = -1; + this._endIndex = -1; } enter = (e: React.KeyboardEvent) => { if (e.key === "Enter") { this.submitSearch(); } } @@ -114,6 +116,25 @@ export class SearchBox extends React.Component { }); } + getResultsHelp = async (query: string) => { + // docs length = this._results.length --> number of docs that are shown (after filtering) + // stops looking once this._results.length >= maxDisplayIndex + // max search index = number of results looked through in solr (solr index) --> increments of 10 + // max display index = number of documents that SHOULD be shown (should include buffer), this._endIndex + buffer (= 4) + // currentRequest = promise | undefined, if undefined, can run and look for more. If not undefined, then there is a request in progress and it cannot look for more yet + + let buffer = 4; + let maxDisplayIndex: number = this._endIndex + buffer; + let curRequest = undefined; + + + while (this._results.length < maxDisplayIndex) { + if (curRequest === undefined) { + + } + } + } + @action getResults = async (query: string, count: number) => { let resDocs = []; @@ -144,91 +165,72 @@ export class SearchBox extends React.Component { this._currentIndex += docs.length; - // console.log(`ResDocs: ${resDocs.length}`); + console.log(`ResDocs: ${resDocs.length}`); console.log(`CurrIndex: ${this._currentIndex}`); } // console.log(this.getResults2(query, count, [])); return resDocs; } - @action - getResults2 = async (query: string, count: number, docs: Doc[]) => { - // let buffer = 4; - // let goalIndex = this._endIndex + count; - // let bottomBound = Math.floor(goalIndex / 10) * 10; - // let tempIndex = this._currentIndex; - // let goalNum = this._endIndex + buffer; - let resDocs: Doc[] = docs; - - // let topBound = bottomBound - 10; - // let unfilteredDocs: Doc[]; - // let unfilteredFound: number; - // means this has already been fetched - // if (this._fetchedIndices.includes(topBound)) { - // return; - // } - - let index = count <= 0 ? undefined : this._currentIndex; - // let index = this._currentIndex; - if (index) { - let topBound = Math.ceil(index / 10) * 10; - if (this._fetchedIndices.includes(topBound)) { - // console.log("returning NOTHING") - return resDocs; - } - let startIndex = this._fetchedIndices[this._fetchedIndices.length - 1]; - let endIndex = startIndex + 10; - this._fetchedIndices.push(endIndex); - console.log(this._fetchedIndices) - let prom: Promise = SearchUtil.Search(query, true, index, 10); - - prom.then((res: SearchUtil.DocSearchResult) => { - count = Math.min(res.numFound, count); - console.log(res.docs); - let filteredDocs = FilterBox.Instance.filterDocsByType(res.docs); - - if (res.numFound !== this._numTotalResults && this._numTotalResults === 0) { - this._numTotalResults = res.numFound; - } - - resDocs.push(...filteredDocs); - - this._currentIndex += res.docs.length; - - if (resDocs.length < count) { - return this.getResults2(query, count - resDocs.length, resDocs); - // resDocs = await this.getResults2(query, count - filteredDocs.length, resDocs); - } - - return resDocs; - }) - } - return resDocs; - //this is the upper bound of the last - // let index = this._fetchedIndices[this._fetchedIndices.length - 1]; - // let prom: Promise = SearchUtil.Search(query, true, index, 10); - - // prom.then((res: SearchUtil.DocSearchResult) => { - // // unfilteredDocs = res.docs; - // // unfilteredFound = res.numFound; - - // count = Math.min(res.numFound, count); - // let filteredDocs = FilterBox.Instance.filterDocsByType(res.docs); - - // if (res.numFound !== this._numTotalResults && this._numTotalResults === 0) { - // console.log(`Total: ${res.numFound}`); - // this._numTotalResults = res.numFound; - // } - - // resDocs.push(...filteredDocs); - - // this._currentIndex += res.docs.length; - // }) - - // console.log(prom); - - - } + // @action + // getResults2 = async (query: string, count: number, docs: Doc[]) => { + // console.log("results 2") + // let buffer = 4; + // // let goalIndex = this._endIndex + count; + // // let bottomBound = Math.floor(goalIndex / 10) * 10; + // let tempIndex = this._currentIndex; + // let goalNum = this._endIndex + buffer; + // let resDocs: Doc[] = docs; + + // // let topBound = bottomBound - 10; + // // let unfilteredDocs: Doc[]; + // // let unfilteredFound: number; + // // means this has already been fetched + // // if (this._fetchedIndices.includes(topBound)) { + // // return; + // // } + + // let index = count <= 0 ? undefined : this._currentIndex; + // if (index) { + // let topBound = Math.ceil(index / 10) * 10; + // if (this._fetchedIndices.includes(topBound)) { + // return; + // } + // let startIndex = this._fetchedIndices[this._fetchedIndices.length - 1]; + // let endIndex = startIndex + 10; + // this._fetchedIndices.push(endIndex); + // console.log(this._fetchedIndices) + // let prom: Promise = SearchUtil.Search(query, true, index, 10); + + // prom.then((res: SearchUtil.DocSearchResult) => { + // count = Math.min(res.numFound, count); + // console.log(res.docs); + // let filteredDocs = FilterBox.Instance.filterDocsByType(res.docs); + + // if (res.numFound !== this._numTotalResults && this._numTotalResults === 0) { + // this._numTotalResults = res.numFound; + // } + + // resDocs.push(...filteredDocs); + + // this._currentIndex += res.docs.length; + + // if (resDocs.length <= count) { + // runInAction(() => { + // return this.getResults2(query, count, resDocs); + // }); + // } + // else { + // return resDocs; + // } + // // console.log(tempIndex); + // console.log(resDocs.length); + // }) + + // } + + + // } collectionRef = React.createRef(); startDragCollection = async () => { @@ -291,8 +293,8 @@ export class SearchBox extends React.Component { this._visibleElements = []; this._currentIndex = 0; this._numTotalResults = 0; - this._startIndex = 0; - this._endIndex = 12; + this._startIndex = -1; + this._endIndex = -1; } resultsScrolled = flow(function* (this: SearchBox, e?: React.UIEvent) { @@ -304,9 +306,10 @@ export class SearchBox extends React.Component { if (startIndex === this._startIndex && endIndex === this._endIndex) { return; } - + console.log("_________________________________________________________________________________________________________") console.log(`START: ${startIndex}`); console.log(`END: ${endIndex}`); + this._startIndex = startIndex; this._endIndex = endIndex; @@ -339,7 +342,6 @@ export class SearchBox extends React.Component { if (i >= this._results.length) { // _________________________________________________________________________________________________ let results: Doc[] = yield this.getResults(this._searchString, i + 1 - this._results.length); - console.log(results) if (results.length !== 0) { runInAction(() => { this._results.push(...results); @@ -362,7 +364,6 @@ export class SearchBox extends React.Component { } } } - console.log("_________________________________________________________________________________________________________") }); render() { -- cgit v1.2.3-70-g09d2 From a56eb6c5dde8a7015932faec094cbe83bf0a825b Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 10 Jul 2019 21:18:44 -0400 Subject: added lastmodified time to text data extension doc. now need to figure out how to get at it. --- src/client/util/DocumentManager.ts | 2 +- .../views/collections/CollectionTreeView.tsx | 23 ++++++++-------- src/client/views/nodes/DocumentView.tsx | 4 +-- src/client/views/nodes/FormattedTextBox.tsx | 32 ++++++++++++++-------- .../views/presentationview/PresentationElement.tsx | 4 +-- src/client/views/search/SearchItem.tsx | 6 ++-- src/new_fields/Types.ts | 4 +++ 7 files changed, 45 insertions(+), 30 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index acd8dcef7..8fa460bca 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -106,7 +106,7 @@ export class DocumentManager { @computed public get LinkedDocumentViews() { - let pairs = DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush, false)).reduce((pairs, dv) => { + let pairs = DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush)).reduce((pairs, dv) => { let linksList = LinkManager.Instance.getAllRelatedLinks(dv.props.Document); pairs.push(...linksList.reduce((pairs, link) => { if (link) { diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index d7725f444..d90c78f85 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -1,7 +1,7 @@ import { library } from '@fortawesome/fontawesome-svg-core'; import { faAngleRight, faCamera, faExpand, faTrash, faBell, faCaretDown, faCaretRight, faCaretSquareDown, faCaretSquareRight, faTrashAlt } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, observable, trace } from "mobx"; +import { action, computed, observable, trace, untracked } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast, HeightSym, WidthSym, Opt } from '../../../new_fields/Doc'; import { Id } from '../../../new_fields/FieldSymbols'; @@ -73,9 +73,11 @@ class TreeView extends React.Component { @observable _collapsed: boolean = true; @computed get fieldKey() { - let keys = Array.from(Object.keys(this.resolvedDataDoc)); + trace(); + let keys = Array.from(Object.keys(this.resolvedDataDoc)); // bcz: Argh -- make untracked to avoid this rerunning whenever 'libraryBrush' is set if (this.resolvedDataDoc.proto instanceof Doc) { - keys.push(...Array.from(Object.keys(this.resolvedDataDoc.proto))); + let arr = Array.from(Object.keys(this.resolvedDataDoc.proto!));// bcz: Argh -- make untracked to avoid this rerunning whenever 'libraryBrush' is set + keys.push(...arr); while (keys.indexOf("proto") !== -1) keys.splice(keys.indexOf("proto"), 1); } let keyList: string[] = []; @@ -113,12 +115,12 @@ class TreeView extends React.Component { } } onPointerLeave = (e: React.PointerEvent): void => { - this.props.document.libraryBrush = false; + this.props.document.libraryBrush = undefined; this._header!.current!.className = "treeViewItem-header"; document.removeEventListener("pointermove", this.onDragMove, true); } onDragMove = (e: PointerEvent): void => { - this.props.document.libraryBrush = false; + this.props.document.libraryBrush = undefined; let x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY); let rect = this._header!.current!.getBoundingClientRect(); let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2); @@ -203,7 +205,7 @@ class TreeView extends React.Component { let onItemDown = SetupDrag(reference, () => this.resolvedDataDoc, this.move, this.props.dropAction, this.props.treeViewId, true); let headerElements = ( - { let ind = this.keyList.indexOf(this._chosenKey); ind = (ind + 1) % this.keyList.length; @@ -219,8 +221,8 @@ class TreeView extends React.Component { return <>
@@ -354,7 +356,7 @@ class TreeView extends React.Component { ; } else { let layoutDoc = Doc.expandTemplateLayout(this.props.document, this.props.dataDoc); - contentElement =
+ contentElement =
{ dataDoc={dataDoc} containingCollection={containingCollection} treeViewId={treeViewId} - key={child[Id]} + key={child[Id] + "child " + i} indentDocument={indent} renderDepth={renderDepth} deleteDoc={remove} @@ -526,7 +528,6 @@ export class CollectionTreeView extends CollectionSubView(Document) { let dropAction = StrCast(this.props.Document.dropAction) as dropActionType; let addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before); let moveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc); - return !this.childDocs ? (null) : (
(Docu fullScreenAlias.templates = new List(); this.props.addDocTab(fullScreenAlias, this.dataDoc, "inTab"); SelectionManager.DeselectAll(); - this.props.Document.libraryBrush = false; + this.props.Document.libraryBrush = undefined; } else if (CurrentUserUtils.MainDocId !== this.props.Document[Id] && (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && @@ -575,7 +575,7 @@ export class DocumentView extends DocComponent(Docu } onPointerEnter = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = true; }; - onPointerLeave = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = false; }; + onPointerLeave = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = undefined; }; isSelected = () => SelectionManager.IsSelected(this); @action select = (ctrlPressed: boolean) => { SelectionManager.SelectDoc(this, ctrlPressed); }; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index d84ad0918..5475aa2b2 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -9,11 +9,11 @@ import { NodeType } from 'prosemirror-model'; import { EditorState, Plugin, Transaction } from "prosemirror-state"; import { EditorView } from "prosemirror-view"; import { Doc, Opt } from "../../../new_fields/Doc"; -import { Id } from '../../../new_fields/FieldSymbols'; +import { Id, Copy } from '../../../new_fields/FieldSymbols'; import { List } from '../../../new_fields/List'; import { RichTextField } from "../../../new_fields/RichTextField"; import { createSchema, listSpec, makeInterface } from "../../../new_fields/Schema"; -import { BoolCast, Cast, NumCast, StrCast } from "../../../new_fields/Types"; +import { BoolCast, Cast, NumCast, StrCast, DateCast } from "../../../new_fields/Types"; import { DocServer } from "../../DocServer"; import { Docs } from '../../documents/Documents'; import { DocumentManager } from '../../util/DocumentManager'; @@ -33,6 +33,8 @@ import { Templates } from '../Templates'; import { FieldView, FieldViewProps } from "./FieldView"; import "./FormattedTextBox.scss"; import React = require("react"); +import { DateField } from '../../../new_fields/DateField'; +import { thisExpression } from 'babel-types'; library.add(faEdit); library.add(faSmile); @@ -68,6 +70,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe private _applyingChange: boolean = false; private _linkClicked = ""; private _reactionDisposer: Opt; + private _textReactionDisposer: Opt; private _proxyReactionDisposer: Opt; private dropDisposer?: DragManager.DragDropDisposer; public get CurrentDiv(): HTMLDivElement { return this._ref.current!; } @@ -131,6 +134,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe this._editorView.updateState(state); this._applyingChange = true; if (this.extensionDoc) this.extensionDoc.text = state.doc.textBetween(0, state.doc.content.size, "\n\n"); + if (this.extensionDoc) this.extensionDoc.lastModified = new DateField(new Date(Date.now())); this.dataDoc[this.props.fieldKey] = new RichTextField(JSON.stringify(state.toJSON())); this._applyingChange = false; let title = StrCast(this.dataDoc.title); @@ -233,6 +237,17 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe this._editorView.updateState(EditorState.fromJSON(config, JSON.parse(field2))); } ); + + this._textReactionDisposer = reaction( + () => this.extensionDoc, + () => { + if (this.dataDoc.text || this.dataDoc.lastModified) { + this.extensionDoc.text = this.dataDoc.text; + this.extensionDoc.lastModified = DateCast(this.dataDoc.lastModified)[Copy](); + this.dataDoc.text = undefined; + this.dataDoc.lastModified = undefined; + } + }, { fireImmediately: true }); this.setupEditor(config, this.dataDoc, this.props.fieldKey); } @@ -271,15 +286,10 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } componentWillUnmount() { - if (this._editorView) { - this._editorView.destroy(); - } - if (this._reactionDisposer) { - this._reactionDisposer(); - } - if (this._proxyReactionDisposer) { - this._proxyReactionDisposer(); - } + this._editorView && this._editorView.destroy(); + this._reactionDisposer && this._reactionDisposer(); + this._proxyReactionDisposer && this._proxyReactionDisposer(); + this._textReactionDisposer && this._textReactionDisposer(); } onPointerDown = (e: React.PointerEvent): void => { diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index 6896ee452..a16d7bc76 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -370,14 +370,14 @@ export default class PresentationElement extends React.Component { p.document.libraryBrush = true; }; - let onLeave = (e: React.PointerEvent) => { p.document.libraryBrush = false; }; + let onLeave = (e: React.PointerEvent) => { p.document.libraryBrush = undefined; }; return (
{ p.gotoDocument(p.index, NumCast(this.props.mainDocument.selectedDoc)); e.stopPropagation(); }}> diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx index 804ffa7f5..87cae5487 100644 --- a/src/client/views/search/SearchItem.tsx +++ b/src/client/views/search/SearchItem.tsx @@ -206,13 +206,13 @@ export class SearchItem extends React.Component { let doc1 = Cast(this.props.doc.anchor1, Doc, null); let doc2 = Cast(this.props.doc.anchor2, Doc, null); - doc1 && (doc1.libraryBrush = false); - doc2 && (doc2.libraryBrush = false); + doc1 && (doc1.libraryBrush = undefined); + doc2 && (doc2.libraryBrush = undefined); } } else { let docViews: DocumentView[] = DocumentManager.Instance.getAllDocumentViews(this.props.doc); docViews.forEach(element => { - element.props.Document.libraryBrush = false; + element.props.Document.libraryBrush = undefined; }); } } diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts index 39d384d64..f8a4a30b4 100644 --- a/src/new_fields/Types.ts +++ b/src/new_fields/Types.ts @@ -1,6 +1,7 @@ import { Field, Opt, FieldResult, Doc } from "./Doc"; import { List } from "./List"; import { RefField } from "./RefField"; +import { DateField } from "./DateField"; export type ToType = T extends "string" ? string : @@ -80,6 +81,9 @@ export function StrCast(field: FieldResult, defaultVal: string | null = "") { export function BoolCast(field: FieldResult, defaultVal: boolean | null = null) { return Cast(field, "boolean", defaultVal); } +export function DateCast(field: FieldResult) { + return Cast(field, DateField, null); +} type WithoutList = T extends List ? (R extends RefField ? (R | Promise)[] : R[]) : T; -- cgit v1.2.3-70-g09d2 From 9c4ed0eba1ee65271435a950f50fcbc85417eb0b Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Thu, 11 Jul 2019 02:32:27 -0400 Subject: naming cleanup --- src/Utils.ts | 6 +- src/client/DocServer.ts | 4 +- src/client/documents/Documents.ts | 84 +++++++++++----------- .../views/collections/CollectionStackingView.tsx | 4 +- .../views/collections/CollectionTreeView.tsx | 4 +- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/LinkMenu.tsx | 2 +- src/client/views/search/FilterBox.tsx | 4 +- src/client/views/search/IconBar.tsx | 4 +- src/client/views/search/IconButton.tsx | 42 +++++------ src/client/views/search/SearchItem.tsx | 26 +++---- 11 files changed, 93 insertions(+), 89 deletions(-) (limited to 'src/client/views/search') diff --git a/src/Utils.ts b/src/Utils.ts index a62f9b4ff..e8a80bdc3 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -78,9 +78,9 @@ export class Utils { socket.emit(message.Message, args); } - public static emitCallback(socket: Socket | SocketIOClient.Socket, message: Message, args: T): Promise; - public static emitCallback(socket: Socket | SocketIOClient.Socket, message: Message, args: T, fn: (args: any) => any): void; - public static emitCallback(socket: Socket | SocketIOClient.Socket, message: Message, args: T, fn?: (args: any) => any): void | Promise { + public static EmitCallback(socket: Socket | SocketIOClient.Socket, message: Message, args: T): Promise; + public static EmitCallback(socket: Socket | SocketIOClient.Socket, message: Message, args: T, fn: (args: any) => any): void; + public static EmitCallback(socket: Socket | SocketIOClient.Socket, message: Message, args: T, fn?: (args: any) => any): void | Promise { this.log("Emit", message.Name, args, false); if (fn) { socket.emit(message.Message, args, this.loggingCallback('Receiving', fn, message.Name)); diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index 895177841..d05793ea2 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -109,7 +109,7 @@ export namespace DocServer { // synchronously, we emit a single callback to the server requesting the serialized (i.e. represented by a string) // field for the given ids. This returns a promise, which, when resolved, indicates the the JSON serialized version of // the field has been returned from the server - const getSerializedField = Utils.emitCallback(_socket, MessageStore.GetRefField, id); + const getSerializedField = Utils.EmitCallback(_socket, MessageStore.GetRefField, id); // when the serialized RefField has been received, go head and begin deserializing it into an object. // Here, once deserialized, we also invoke .proto to 'load' the document's prototype, which ensures that all @@ -179,7 +179,7 @@ export namespace DocServer { // 2) synchronously, we emit a single callback to the server requesting the serialized (i.e. represented by a string) // fields for the given ids. This returns a promise, which, when resolved, indicates that all the JSON serialized versions of // the fields have been returned from the server - const getSerializedFields: Promise = Utils.emitCallback(_socket, MessageStore.GetRefFields, requestedIds); + const getSerializedFields: Promise = Utils.EmitCallback(_socket, MessageStore.GetRefFields, requestedIds); // 3) when the serialized RefFields have been received, go head and begin deserializing them into objects. // Here, once deserialized, we also invoke .proto to 'load' the documents' prototypes, which ensures that all diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index b2f69d7af..5a3f9574f 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -41,7 +41,7 @@ import { Scripting } from "../util/Scripting"; var requestImageSize = require('../util/request-image-size'); var path = require('path'); -export enum DocTypes { +export enum DocumentType { NONE = "none", TEXT = "text", HIST = "histogram", @@ -60,13 +60,13 @@ export enum DocTypes { export namespace DocTypeUtils { export function values(includeNone: boolean = true): string[] { - let types = Object.values(DocTypes); - return includeNone ? types : types.filter(key => key !== DocTypes.NONE); + let types = Object.values(DocumentType); + return includeNone ? types : types.filter(key => key !== DocumentType.NONE); } export function keys(includeNone: boolean = true): string[] { - let types = Object.keys(DocTypes); - return includeNone ? types : types.filter(key => key !== DocTypes.NONE); + let types = Object.keys(DocumentType); + return includeNone ? types : types.filter(key => key !== DocumentType.NONE); } } @@ -104,55 +104,55 @@ export namespace Docs { export namespace Prototypes { type PrototypeTemplate = { options?: Partial, primary: string, background?: string }; - type TemplateMap = Map; - type PrototypeMap = Map; + type TemplateMap = Map; + type PrototypeMap = Map; const TemplateMap: TemplateMap = new Map([ - [DocTypes.TEXT, { + [DocumentType.TEXT, { options: { height: 150, backgroundColor: "#f1efeb" }, primary: FormattedTextBox.LayoutString() }], - [DocTypes.HIST, { + [DocumentType.HIST, { options: { nativeWidth: 600, curPage: 0 }, primary: CollectionView.LayoutString("annotations"), background: HistogramBox.LayoutString() }], - [DocTypes.IMG, { + [DocumentType.IMG, { options: { height: 300, backgroundColor: "black" }, primary: CollectionView.LayoutString("annotations"), background: ImageBox.LayoutString() }], - [DocTypes.WEB, { + [DocumentType.WEB, { options: { height: 300 }, primary: WebBox.LayoutString() }], - [DocTypes.COL, { + [DocumentType.COL, { options: { panX: 0, panY: 0, scale: 1, width: 500, height: 500 }, primary: CollectionView.LayoutString() }], - [DocTypes.KVP, { + [DocumentType.KVP, { options: { height: 150 }, primary: KeyValueBox.LayoutString() }], - [DocTypes.VID, { + [DocumentType.VID, { options: { nativeWidth: 600, curPage: 0 }, primary: CollectionVideoView.LayoutString("annotations"), background: VideoBox.LayoutString() }], - [DocTypes.AUDIO, { + [DocumentType.AUDIO, { options: { height: 150 }, primary: AudioBox.LayoutString() }], - [DocTypes.PDF, { + [DocumentType.PDF, { options: { nativeWidth: 1200, curPage: 1 }, primary: CollectionPDFView.LayoutString("annotations"), background: PDFBox.LayoutString() }], - [DocTypes.ICON, { + [DocumentType.ICON, { options: { width: Number(MINIMIZED_ICON_SIZE), height: Number(MINIMIZED_ICON_SIZE) }, primary: IconBox.LayoutString() }], - [DocTypes.IMPORT, { + [DocumentType.IMPORT, { options: { height: 150 }, primary: DirectoryImportBox.LayoutString() }] @@ -178,16 +178,20 @@ export namespace Docs { // fetch the actual prototype documents from the server let actualProtos = await DocServer.GetRefFields(prototypeIds); + // update this object to include any default values: DocumentOptions for all prototypes let defaultOptions: DocumentOptions = { x: 0, y: 0, width: 300 }; prototypeIds.map(id => { let existing = actualProtos[id] as Doc; - let type = id.replace(suffix, "") as DocTypes; + let type = id.replace(suffix, "") as DocumentType; + // get or create prototype of the specified type... let target = existing || buildPrototype(type, id, defaultOptions); + // ...and set it if not undefined (can be undefined only if TemplateMap does not contain + // an entry dedicated to the given DocumentType) target && PrototypeMap.set(type, target); }); } - export function get(type: DocTypes) { + export function get(type: DocumentType) { return PrototypeMap.get(type)!; } @@ -203,7 +207,7 @@ export namespace Docs { * @param options any value specified in the DocumentOptions object likewise * becomes the default value for that key for all delegates */ - function buildPrototype(type: DocTypes, prototypeId: string, defaultOptions: DocumentOptions): Opt { + function buildPrototype(type: DocumentType, prototypeId: string, defaultOptions: DocumentOptions): Opt { let template = TemplateMap.get(type); if (!template) { return undefined; @@ -279,7 +283,7 @@ export namespace Docs { } export function ImageDocument(url: string, options: DocumentOptions = {}) { - let inst = InstanceFromProto(Prototypes.get(DocTypes.IMG), new ImageField(new URL(url)), { title: path.basename(url), ...options }); + let inst = InstanceFromProto(Prototypes.get(DocumentType.IMG), new ImageField(new URL(url)), { title: path.basename(url), ...options }); requestImageSize(window.origin + RouteStore.corsProxy + "/" + url) .then((size: any) => { let aspect = size.height / size.width; @@ -294,27 +298,27 @@ export namespace Docs { } export function VideoDocument(url: string, options: DocumentOptions = {}) { - return InstanceFromProto(Prototypes.get(DocTypes.VID), new VideoField(new URL(url)), options); + return InstanceFromProto(Prototypes.get(DocumentType.VID), new VideoField(new URL(url)), options); } export function AudioDocument(url: string, options: DocumentOptions = {}) { - return InstanceFromProto(Prototypes.get(DocTypes.AUDIO), new AudioField(new URL(url)), options); + return InstanceFromProto(Prototypes.get(DocumentType.AUDIO), new AudioField(new URL(url)), options); } export function HistogramDocument(histoOp: HistogramOperation, options: DocumentOptions = {}) { - return InstanceFromProto(Prototypes.get(DocTypes.HIST), new HistogramField(histoOp), options); + return InstanceFromProto(Prototypes.get(DocumentType.HIST), new HistogramField(histoOp), options); } export function TextDocument(options: DocumentOptions = {}) { - return InstanceFromProto(Prototypes.get(DocTypes.TEXT), "", options); + return InstanceFromProto(Prototypes.get(DocumentType.TEXT), "", options); } export function IconDocument(icon: string, options: DocumentOptions = {}) { - return InstanceFromProto(Prototypes.get(DocTypes.ICON), new IconField(icon), options); + return InstanceFromProto(Prototypes.get(DocumentType.ICON), new IconField(icon), options); } export function PdfDocument(url: string, options: DocumentOptions = {}) { - return InstanceFromProto(Prototypes.get(DocTypes.PDF), new PdfField(new URL(url)), options); + return InstanceFromProto(Prototypes.get(DocumentType.PDF), new PdfField(new URL(url)), options); } export async function DBDocument(url: string, options: DocumentOptions = {}, columnOptions: DocumentOptions = {}) { @@ -349,42 +353,42 @@ export namespace Docs { } export function WebDocument(url: string, options: DocumentOptions = {}) { - return InstanceFromProto(Prototypes.get(DocTypes.WEB), new WebField(new URL(url)), options); + return InstanceFromProto(Prototypes.get(DocumentType.WEB), new WebField(new URL(url)), options); } export function HtmlDocument(html: string, options: DocumentOptions = {}) { - return InstanceFromProto(Prototypes.get(DocTypes.WEB), new HtmlField(html), options); + return InstanceFromProto(Prototypes.get(DocumentType.WEB), new HtmlField(html), options); } export function KVPDocument(document: Doc, options: DocumentOptions = {}) { - return InstanceFromProto(Prototypes.get(DocTypes.KVP), document, { title: document.title + ".kvp", ...options }); + return InstanceFromProto(Prototypes.get(DocumentType.KVP), document, { title: document.title + ".kvp", ...options }); } export function FreeformDocument(documents: Array, options: DocumentOptions, makePrototype: boolean = true) { if (!makePrototype) { - return MakeDataDelegate(Prototypes.get(DocTypes.COL), { ...options, viewType: CollectionViewType.Freeform }, new List(documents)); + return MakeDataDelegate(Prototypes.get(DocumentType.COL), { ...options, viewType: CollectionViewType.Freeform }, new List(documents)); } - return InstanceFromProto(Prototypes.get(DocTypes.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Freeform }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Freeform }); } export function SchemaDocument(schemaColumns: string[], documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocTypes.COL), new List(documents), { schemaColumns: new List(schemaColumns), ...options, viewType: CollectionViewType.Schema }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(schemaColumns), ...options, viewType: CollectionViewType.Schema }); } export function TreeDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocTypes.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Tree }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Tree }); } export function StackingDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocTypes.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Stacking }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Stacking }); } export function DockDocument(documents: Array, config: string, options: DocumentOptions, id?: string) { - return InstanceFromProto(Prototypes.get(DocTypes.COL), new List(documents), { ...options, viewType: CollectionViewType.Docking, dockingConfig: config }, id); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, viewType: CollectionViewType.Docking, dockingConfig: config }, id); } export function DirectoryImportDocument(options: DocumentOptions = {}) { - return InstanceFromProto(Prototypes.get(DocTypes.IMPORT), new List(), options); + return InstanceFromProto(Prototypes.get(DocumentType.IMPORT), new List(), options); } export type DocConfig = { @@ -538,14 +542,14 @@ export namespace DocUtils { UndoManager.RunInBatch(() => { let linkDoc = Docs.Create.TextDocument({ width: 100, height: 30, borderRounding: "100%" }); - linkDoc.type = DocTypes.LINK; + linkDoc.type = DocumentType.LINK; let linkDocProto = Doc.GetProto(linkDoc); linkDocProto.context = targetContext; linkDocProto.title = title === "" ? source.title + " to " + target.title : title; linkDocProto.linkDescription = description; linkDocProto.linkTags = tags; - linkDocProto.type = DocTypes.LINK; + linkDocProto.type = DocumentType.LINK; linkDocProto.anchor1 = source; linkDocProto.anchor1Page = source.curPage; diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 9266fc8fd..d26bf5118 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -12,7 +12,7 @@ import "./CollectionStackingView.scss"; import { CollectionSubView } from "./CollectionSubView"; import { undoBatch } from "../../util/UndoManager"; import { DragManager } from "../../util/DragManager"; -import { DocTypes } from "../../documents/Documents"; +import { DocumentType } from "../../documents/Documents"; import { Transform } from "../../util/Transform"; @observer @@ -50,7 +50,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } overlays = (doc: Doc) => { - return doc.type === DocTypes.IMG ? { title: "title", caption: "caption" } : {}; + return doc.type === DocumentType.IMG ? { title: "title", caption: "caption" } : {}; } getDisplayDoc(layoutDoc: Doc, d: Doc, dxf: () => Transform) { diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index e88f1a9d0..c8c092760 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -9,7 +9,7 @@ import { List } from '../../../new_fields/List'; import { Document, listSpec } from '../../../new_fields/Schema'; import { BoolCast, Cast, NumCast, StrCast } from '../../../new_fields/Types'; import { emptyFunction, Utils } from '../../../Utils'; -import { Docs, DocUtils, DocTypes } from '../../documents/Documents'; +import { Docs, DocUtils, DocumentType } from '../../documents/Documents'; import { DocumentManager } from '../../util/DocumentManager'; import { DragManager, dropActionType, SetupDrag } from "../../util/DragManager"; import { SelectionManager } from '../../util/SelectionManager'; @@ -316,7 +316,7 @@ class TreeView extends React.Component { } @computed get docBounds() { - if (StrCast(this.props.document.type).indexOf(DocTypes.COL) === -1) return undefined; + if (StrCast(this.props.document.type).indexOf(DocumentType.COL) === -1) return undefined; let layoutDoc = Doc.expandTemplateLayout(this.props.document, this.props.dataDoc); return Doc.ComputeContentBounds(layoutDoc); } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 718552dc9..27b45db76 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -10,7 +10,7 @@ import { BoolCast, Cast, FieldValue, StrCast, NumCast, PromiseValue } from "../. import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; import { emptyFunction, Utils, returnFalse, returnTrue } from "../../../Utils"; import { DocServer } from "../../DocServer"; -import { Docs, DocUtils, DocTypes } from "../../documents/Documents"; +import { Docs, DocUtils, DocumentType } from "../../documents/Documents"; import { DocumentManager } from "../../util/DocumentManager"; import { DragManager, dropActionType } from "../../util/DragManager"; import { SearchUtil } from "../../util/SearchUtil"; diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx index cccf3c329..1eda7d1fb 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -14,7 +14,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; library.add(faTrash); import { Cast, FieldValue, StrCast } from "../../../new_fields/Types"; import { Id } from "../../../new_fields/FieldSymbols"; -import { DocTypes } from "../../documents/Documents"; +import { DocumentType } from "../../documents/Documents"; interface Props { docView: DocumentView; diff --git a/src/client/views/search/FilterBox.tsx b/src/client/views/search/FilterBox.tsx index 23a1b31d8..c6c18f9b4 100644 --- a/src/client/views/search/FilterBox.tsx +++ b/src/client/views/search/FilterBox.tsx @@ -6,7 +6,7 @@ import { faTimes } from '@fortawesome/free-solid-svg-icons'; import { library } from '@fortawesome/fontawesome-svg-core'; import { Doc } from '../../../new_fields/Doc'; import { Id } from '../../../new_fields/FieldSymbols'; -import { DocTypes } from '../../documents/Documents'; +import { DocumentType } from '../../documents/Documents'; import { Cast, StrCast } from '../../../new_fields/Types'; import * as _ from "lodash"; import { ToggleBar } from './ToggleBar'; @@ -32,7 +32,7 @@ export enum Keys { export class FilterBox extends React.Component { static Instance: FilterBox; - public _allIcons: string[] = [DocTypes.AUDIO, DocTypes.COL, DocTypes.HIST, DocTypes.IMG, DocTypes.LINK, DocTypes.PDF, DocTypes.TEXT, DocTypes.VID, DocTypes.WEB]; + public _allIcons: string[] = [DocumentType.AUDIO, DocumentType.COL, DocumentType.HIST, DocumentType.IMG, DocumentType.LINK, DocumentType.PDF, DocumentType.TEXT, DocumentType.VID, DocumentType.WEB]; //if true, any keywords can be used. if false, all keywords are required. @observable private _basicWordStatus: boolean = true; diff --git a/src/client/views/search/IconBar.tsx b/src/client/views/search/IconBar.tsx index 744dd898a..4712b0abc 100644 --- a/src/client/views/search/IconBar.tsx +++ b/src/client/views/search/IconBar.tsx @@ -4,7 +4,7 @@ import { observable, action } from 'mobx'; // import "./SearchBox.scss"; import "./IconBar.scss"; import "./IconButton.scss"; -import { DocTypes } from '../../documents/Documents'; +import { DocumentType } from '../../documents/Documents'; import { faSearch, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote, faMusic, faLink, faChartBar, faGlobeAsia, faBan, faTimesCircle, faCheckCircle } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { library } from '@fortawesome/fontawesome-svg-core'; @@ -63,7 +63,7 @@ export class IconBar extends React.Component {
- +
Select All
diff --git a/src/client/views/search/IconButton.tsx b/src/client/views/search/IconButton.tsx index 23ab42de0..bfe2c7d0b 100644 --- a/src/client/views/search/IconButton.tsx +++ b/src/client/views/search/IconButton.tsx @@ -6,7 +6,7 @@ import "./IconButton.scss"; import { faSearch, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote, faMusic, faLink, faChartBar, faGlobeAsia, faBan, faVideo, faCaretDown } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { library, icon } from '@fortawesome/fontawesome-svg-core'; -import { DocTypes } from '../../documents/Documents'; +import { DocumentType } from '../../documents/Documents'; import '../globalCssVariables.scss'; import * as _ from "lodash"; import { IconBar } from './IconBar'; @@ -80,25 +80,25 @@ export class IconButton extends React.Component{ @action.bound getIcon() { switch (this.props.type) { - case (DocTypes.NONE): + case (DocumentType.NONE): return faBan; - case (DocTypes.AUDIO): + case (DocumentType.AUDIO): return faMusic; - case (DocTypes.COL): + case (DocumentType.COL): return faObjectGroup; - case (DocTypes.HIST): + case (DocumentType.HIST): return faChartBar; - case (DocTypes.IMG): + case (DocumentType.IMG): return faImage; - case (DocTypes.LINK): + case (DocumentType.LINK): return faLink; - case (DocTypes.PDF): + case (DocumentType.PDF): return faFilePdf; - case (DocTypes.TEXT): + case (DocumentType.TEXT): return faStickyNote; - case (DocTypes.VID): + case (DocumentType.VID): return faVideo; - case (DocTypes.WEB): + case (DocumentType.WEB): return faGlobeAsia; default: return faCaretDown; @@ -149,25 +149,25 @@ export class IconButton extends React.Component{ getFA = () => { switch (this.props.type) { - case (DocTypes.NONE): + case (DocumentType.NONE): return (); - case (DocTypes.AUDIO): + case (DocumentType.AUDIO): return (); - case (DocTypes.COL): + case (DocumentType.COL): return (); - case (DocTypes.HIST): + case (DocumentType.HIST): return (); - case (DocTypes.IMG): + case (DocumentType.IMG): return (); - case (DocTypes.LINK): + case (DocumentType.LINK): return (); - case (DocTypes.PDF): + case (DocumentType.PDF): return (); - case (DocTypes.TEXT): + case (DocumentType.TEXT): return (); - case (DocTypes.VID): + case (DocumentType.VID): return (); - case (DocTypes.WEB): + case (DocumentType.WEB): return (); default: return (); diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx index 87cae5487..b34103254 100644 --- a/src/client/views/search/SearchItem.tsx +++ b/src/client/views/search/SearchItem.tsx @@ -8,7 +8,7 @@ import { Doc, DocListCast, HeightSym, WidthSym } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; import { Cast, NumCast, StrCast } from "../../../new_fields/Types"; import { emptyFunction, returnFalse, returnOne, Utils } from "../../../Utils"; -import { DocTypes } from "../../documents/Documents"; +import { DocumentType } from "../../documents/Documents"; import { DocumentManager } from "../../util/DocumentManager"; import { SetupDrag, DragManager } from "../../util/DragManager"; import { LinkManager } from "../../util/LinkManager"; @@ -119,7 +119,7 @@ export class SearchItem extends React.Component { onPointerEnter={action(() => this._displayDim = this._useIcons ? 50 : Number(SEARCH_THUMBNAIL_SIZE))} onPointerLeave={action(() => this._displayDim = 50)} > { } let layoutresult = StrCast(this.props.doc.type); - let button = layoutresult.indexOf(DocTypes.PDF) !== -1 ? faFilePdf : - layoutresult.indexOf(DocTypes.IMG) !== -1 ? faImage : - layoutresult.indexOf(DocTypes.TEXT) !== -1 ? faStickyNote : - layoutresult.indexOf(DocTypes.VID) !== -1 ? faFilm : - layoutresult.indexOf(DocTypes.COL) !== -1 ? faObjectGroup : - layoutresult.indexOf(DocTypes.AUDIO) !== -1 ? faMusic : - layoutresult.indexOf(DocTypes.LINK) !== -1 ? faLink : - layoutresult.indexOf(DocTypes.HIST) !== -1 ? faChartBar : - layoutresult.indexOf(DocTypes.WEB) !== -1 ? faGlobeAsia : + let button = layoutresult.indexOf(DocumentType.PDF) !== -1 ? faFilePdf : + layoutresult.indexOf(DocumentType.IMG) !== -1 ? faImage : + layoutresult.indexOf(DocumentType.TEXT) !== -1 ? faStickyNote : + layoutresult.indexOf(DocumentType.VID) !== -1 ? faFilm : + layoutresult.indexOf(DocumentType.COL) !== -1 ? faObjectGroup : + layoutresult.indexOf(DocumentType.AUDIO) !== -1 ? faMusic : + layoutresult.indexOf(DocumentType.LINK) !== -1 ? faLink : + layoutresult.indexOf(DocumentType.HIST) !== -1 ? faChartBar : + layoutresult.indexOf(DocumentType.WEB) !== -1 ? faGlobeAsia : faCaretUp; return
{ this._useIcons = false; this._displayDim = Number(SEARCH_THUMBNAIL_SIZE); })} > @@ -184,7 +184,7 @@ export class SearchItem extends React.Component { pointerDown = (e: React.PointerEvent) => { e.preventDefault(); e.button === 0 && SearchBox.Instance.openSearch(e); } highlightDoc = (e: React.PointerEvent) => { - if (this.props.doc.type === DocTypes.LINK) { + if (this.props.doc.type === DocumentType.LINK) { if (this.props.doc.anchor1 && this.props.doc.anchor2) { let doc1 = Cast(this.props.doc.anchor1, Doc, null); @@ -201,7 +201,7 @@ export class SearchItem extends React.Component { } unHighlightDoc = (e: React.PointerEvent) => { - if (this.props.doc.type === DocTypes.LINK) { + if (this.props.doc.type === DocumentType.LINK) { if (this.props.doc.anchor1 && this.props.doc.anchor2) { let doc1 = Cast(this.props.doc.anchor1, Doc, null); -- cgit v1.2.3-70-g09d2 From a9ecaef0c7d870136401dfbb687afdb9dd2843f4 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 11 Jul 2019 11:00:09 -0400 Subject: fixed fitToBox stuff. --- .../views/collections/CollectionSchemaView.tsx | 2 +- .../views/collections/CollectionTreeView.tsx | 12 +++---- .../collectionFreeForm/CollectionFreeFormView.scss | 41 +--------------------- .../collectionFreeForm/CollectionFreeFormView.tsx | 18 +++++++--- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/FieldView.tsx | 2 +- src/client/views/search/SearchItem.tsx | 6 +--- src/new_fields/Doc.ts | 7 ++-- 8 files changed, 27 insertions(+), 63 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 21a2a7dd0..a55549280 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -401,8 +401,8 @@ interface CollectionSchemaPreviewProps { Document?: Doc; DataDocument?: Doc; childDocs?: Doc[]; - fitToBox?: () => number[]; renderDepth: number; + fitToBox?: boolean; width: () => number; height: () => number; showOverlays?: (doc: Doc) => { title?: string, caption?: string }; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 1280d515c..4685e774d 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -315,10 +315,10 @@ class TreeView extends React.Component { return ele; } - @computed get docBounds() { + @computed get boundsOfCollectionDocument() { if (StrCast(this.props.document.type).indexOf(DocTypes.COL) === -1) return undefined; let layoutDoc = Doc.expandTemplateLayout(this.props.document, this.props.dataDoc); - return Doc.ComputeContentBounds(layoutDoc); + return Doc.ComputeContentBounds(DocListCast(layoutDoc.data)); } docWidth = () => { let aspect = NumCast(this.props.document.nativeHeight) / NumCast(this.props.document.nativeWidth); @@ -326,7 +326,7 @@ class TreeView extends React.Component { return NumCast(this.props.document.nativeWidth) ? Math.min(this.props.document[WidthSym](), this.props.panelWidth() - 5) : this.props.panelWidth() - 5; } docHeight = () => { - let bounds = this.docBounds; + let bounds = this.boundsOfCollectionDocument; return Math.min(this.MAX_EMBED_HEIGHT, (() => { let aspect = NumCast(this.props.document.nativeHeight) / NumCast(this.props.document.nativeWidth); if (aspect) return this.docWidth() * aspect; @@ -334,10 +334,6 @@ class TreeView extends React.Component { return NumCast(this.props.document.height) ? NumCast(this.props.document.height) : 50; })()); } - fitToBox = () => { - let bounds = this.docBounds!; - return [(bounds.x + bounds.r) / 2, (bounds.y + bounds.b) / 2, Math.min(this.docHeight() / (bounds.b - bounds.y), this.docWidth() / (bounds.r - bounds.x))]; - } render() { let contentElement: (JSX.Element | null) = null; @@ -360,7 +356,7 @@ class TreeView extends React.Component { Document={layoutDoc} DataDocument={this.resolvedDataDoc} renderDepth={this.props.renderDepth} - fitToBox={this.docBounds && !NumCast(this.props.document.nativeWidth) ? this.fitToBox : undefined} + fitToBox={this.boundsOfCollectionDocument !== undefined} width={this.docWidth} height={this.docHeight} getTransform={this.docTransform} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index 51cfa77b1..ec0e446e9 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -37,6 +37,7 @@ // background-size: 30px 30px; // } box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw; + opacity: 0.99; border: 0px solid $light-color-secondary; border-radius: inherit; box-sizing: border-box; @@ -52,46 +53,6 @@ height: 100%; } - -.collectionfreeformview-overlay { - .collectionfreeformview>.jsx-parser { - position: inherit; - height: 100%; - } - - >.jsx-parser { - position: absolute; - z-index: 0; - } - - .formattedTextBox-cont { - background: $light-color-secondary; - overflow: visible; - } - - opacity: 0.99; - border: 0px solid transparent; - border-radius: inherit; - box-sizing: border-box; - position:absolute; - z-index: -1; - - .marqueeView { - overflow: hidden; - } - - top: 0; - left: 0; - width: 100%; - height: 100%; - - .collectionfreeformview { - .formattedTextBox-cont { - background: yellow; - } - } -} - // selection border...? .border { border-style: solid; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 1363e1ceb..1d1db8de3 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -52,13 +52,22 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { private get _pwidth() { return this.props.PanelWidth(); } private get _pheight() { return this.props.PanelHeight(); } + @computed get contentBounds() { + let bounds = this.props.fitToBox && !NumCast(this.nativeWidth) ? Doc.ComputeContentBounds(DocListCast(this.props.Document.data)) : undefined; + return { + panX: bounds ? (bounds.x + bounds.r) / 2 : this.Document.panX || 0, + panY: bounds ? (bounds.y + bounds.b) / 2 : this.Document.panY || 0, + scale: bounds ? Math.min(this.props.PanelHeight() / (bounds.b - bounds.y), this.props.PanelWidth() / (bounds.r - bounds.x)) : this.Document.scale || 1 + }; + } + @computed get nativeWidth() { return this.Document.nativeWidth || 0; } @computed get nativeHeight() { return this.Document.nativeHeight || 0; } public get isAnnotationOverlay() { return this.props.fieldExt ? true : false; } // fieldExt will be "" or "annotation". should maybe generalize this, or make it more specific (ie, 'annotation' instead of 'fieldExt') private get borderWidth() { return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH; } - private panX = () => this.props.fitToBox ? this.props.fitToBox()[0] : this.Document.panX || 0; - private panY = () => this.props.fitToBox ? this.props.fitToBox()[1] : this.Document.panY || 0; - private zoomScaling = () => this.props.fitToBox ? this.props.fitToBox()[2] : this.Document.scale || 1; + private panX = () => this.contentBounds.panX; + private panY = () => this.contentBounds.panY; + private zoomScaling = () => this.contentBounds.scale; private centeringShiftX = () => !this.nativeWidth ? this._pwidth / 2 : 0; // shift so pan position is at center of window for non-overlay collections private centeringShiftY = () => !this.nativeHeight ? this._pheight / 2 : 0;// shift so pan position is at center of window for non-overlay collections private getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth + 1, -this.borderWidth + 1).translate(-this.centeringShiftX(), -this.centeringShiftY()).transform(this.getLocalTransform()); @@ -502,12 +511,11 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { ...this.views ] render() { - const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`; const easing = () => this.props.Document.panTransformType === "Ease"; Doc.UpdateDocumentExtensionForField(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey); return ( -
; Document: Doc; DataDoc?: Doc; - fitToBox?: () => number[]; + fitToBox?: boolean; addDocument?: (doc: Doc, allowDuplicates?: boolean) => boolean; removeDocument?: (doc: Doc) => boolean; moveDocument?: (doc: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index abd0d9e12..0c084035a 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -31,7 +31,7 @@ export interface FieldViewProps { fieldKey: string; fieldExt: string; leaveNativeSize?: boolean; - fitToBox?: () => number[]; + fitToBox?: boolean; ContainingCollectionView: Opt; Document: Doc; DataDoc?: Doc; diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx index 87cae5487..c34e4febd 100644 --- a/src/client/views/search/SearchItem.tsx +++ b/src/client/views/search/SearchItem.tsx @@ -104,10 +104,6 @@ export class SearchItem extends React.Component { @observable _useIcons = true; @observable _displayDim = 50; - fitToBox = () => { - let bounds = Doc.ComputeContentBounds(this.props.doc); - return [(bounds.x + bounds.r) / 2, (bounds.y + bounds.b) / 2, Number(SEARCH_THUMBNAIL_SIZE) / Math.max((bounds.b - bounds.y), (bounds.r - bounds.x)), this._displayDim]; - } @computed public get DocumentIcon() { if (!this._useIcons) { @@ -119,7 +115,7 @@ export class SearchItem extends React.Component { onPointerEnter={action(() => this._displayDim = this._useIcons ? 50 : Number(SEARCH_THUMBNAIL_SIZE))} onPointerLeave={action(() => this._displayDim = 50)} > { + // + // Computes the bounds of the contents of a set of documents. + // + export function ComputeContentBounds(docList: Doc[]) { + let bounds = docList.reduce((bounds, doc) => { var [sptX, sptY] = [NumCast(doc.x), NumCast(doc.y)]; let [bptX, bptY] = [sptX + doc[WidthSym](), sptY + doc[HeightSym]()]; return { -- cgit v1.2.3-70-g09d2 From 341d173db8f1580f49dc4e9ff429b72d88da16b4 Mon Sep 17 00:00:00 2001 From: monikahedman Date: Thu, 11 Jul 2019 18:01:35 -0400 Subject: end of day 7/11 ho boy we got problems --- src/client/views/search/SearchBox.tsx | 182 +++++++++++++++++++++++----------- 1 file changed, 126 insertions(+), 56 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 1980ddaf2..0816bb9de 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -40,6 +40,7 @@ export class SearchBox extends React.Component { static Instance: SearchBox; private _maxSearchIndex: number = 0; + private _curRequest: Promise | undefined = undefined; constructor(props: any) { super(props); @@ -69,6 +70,8 @@ export class SearchBox extends React.Component { this._numTotalResults = 0; this._startIndex = -1; this._endIndex = -1; + this._curRequest = undefined; + this._maxSearchIndex = 0; } enter = (e: React.KeyboardEvent) => { if (e.key === "Enter") { this.submitSearch(); } } @@ -97,20 +100,43 @@ export class SearchBox extends React.Component { query = FilterBox.Instance.getFinalQuery(query); + // if (this._curRequest !== undefined) { + // this._curRequest.then(() => { + // this._curRequest = undefined; + // this._results = []; + // }); + // } + + // this._results = []; + //if there is no query there should be no result if (query === "") { - results = []; + // results = []; + return; } else { //gets json result into a list of documents that can be used //these are filtered by type + // this._results = []; this._currentIndex = 0; - results = await this.getResults(query, 12); + this._startIndex = 0; + this._endIndex = 12; + // this._curRequest = undefined; + // if (this._curRequest !== undefined) { + // this._curRequest.then(() => { + // this._curRequest = undefined; + // }); + // } + + this._maxSearchIndex = 0; + + // results = await this.getResultsHelp(query); + await this.getResultsHelp(query); } runInAction(() => { this._resultsOpen = true; - this._results = results; + // this._results = results; this._openNoResults = true; this.resultsScrolled(); }); @@ -123,54 +149,85 @@ export class SearchBox extends React.Component { // max display index = number of documents that SHOULD be shown (should include buffer), this._endIndex + buffer (= 4) // currentRequest = promise | undefined, if undefined, can run and look for more. If not undefined, then there is a request in progress and it cannot look for more yet - let buffer = 4; - let maxDisplayIndex: number = this._endIndex + buffer; - let curRequest = undefined; + // let buffer = 4; + // let maxDisplayIndex: number = this._endIndex + buffer; + console.log(`end index: ${this._endIndex}`) + console.log(this._results.length) + + while (this._results.length < this._endIndex) { + console.log("looping") + if (this._curRequest === undefined) { + //start at max search index, get 10, add 10 to max search index + // const { docs, numFound } = await SearchUtil.Search(query, true, this._maxSearchIndex, 10); + // happens at the beginning + // am i gonna need this? + // if (numFound !== this._numTotalResults && this._numTotalResults === 0) { + // this._numTotalResults = numFound; + // } - while (this._results.length < maxDisplayIndex) { - if (curRequest === undefined) { + this._curRequest = SearchUtil.Search(query, true, this._maxSearchIndex, 10); + this._maxSearchIndex += 10; + this._curRequest.then((res: SearchUtil.DocSearchResult) => { + + // happens at the beginning + if (res.numFound !== this._numTotalResults && this._numTotalResults === 0) { + this._numTotalResults = res.numFound; + } + + let filteredDocs = FilterBox.Instance.filterDocsByType(res.docs); + this._results.push(...filteredDocs); + + console.log(this._results) + this._curRequest = undefined; + console.log("setting to undefined") + }); + + //deals with if there are fewer results than can be scrolled through + // if (this._numTotalResults < this._endIndex) { + // break; + // } } } } - @action - getResults = async (query: string, count: number) => { - let resDocs = []; - // count is total number of documents to be shown (i believe) - console.log(`Count: ${count}`); - while (resDocs.length < count) { - let index = count === -1 ? undefined : this._currentIndex; - let num = count === -1 ? undefined : Math.min(this._numTotalResults - this._currentIndex + 1, this._maxNum); - // num found has to be the number of docs before filtering happens - this is the total num - const { docs, numFound } = await SearchUtil.Search(query, true, index, num); - - let filteredDocs = FilterBox.Instance.filterDocsByType(docs); - - // accounts for the fact that there may be fewer documents than the max that are returned - count = Math.min(numFound, count); - - // happens at the beginning - if (numFound !== this._numTotalResults && this._numTotalResults === 0) { - console.log(`Total: ${numFound}`); - this._numTotalResults = numFound; - } + // @action + // getResults = async (query: string, count: number) => { + // let resDocs = []; + // // count is total number of documents to be shown (i believe) + // console.log(`Count: ${count}`); + // while (resDocs.length < count) { + // let index = count === -1 ? undefined : this._currentIndex; + // let num = count === -1 ? undefined : Math.min(this._numTotalResults - this._currentIndex + 1, this._maxNum); + // // num found has to be the number of docs before filtering happens - this is the total num + // const { docs, numFound } = await SearchUtil.Search(query, true, index, num); + + // let filteredDocs = FilterBox.Instance.filterDocsByType(docs); + + // // accounts for the fact that there may be fewer documents than the max that are returned + // count = Math.min(numFound, count); + + // // happens at the beginning + // if (numFound !== this._numTotalResults && this._numTotalResults === 0) { + // console.log(`Total: ${numFound}`); + // this._numTotalResults = numFound; + // } - // if (filteredDocs.length < docs.length) { - // this._numResults -= docs.length - filteredDocs.length; - // console.log(`New Total: ${this._numResults}`); - // } - resDocs.push(...filteredDocs); + // // if (filteredDocs.length < docs.length) { + // // this._numResults -= docs.length - filteredDocs.length; + // // console.log(`New Total: ${this._numResults}`); + // // } + // resDocs.push(...filteredDocs); - this._currentIndex += docs.length; + // this._currentIndex += docs.length; - console.log(`ResDocs: ${resDocs.length}`); - console.log(`CurrIndex: ${this._currentIndex}`); - } - // console.log(this.getResults2(query, count, [])); - return resDocs; - } + // console.log(`ResDocs: ${resDocs.length}`); + // console.log(`CurrIndex: ${this._currentIndex}`); + // } + // // console.log(this.getResults2(query, count, [])); + // return resDocs; + // } // @action // getResults2 = async (query: string, count: number, docs: Doc[]) => { @@ -234,8 +291,9 @@ export class SearchBox extends React.Component { collectionRef = React.createRef(); startDragCollection = async () => { - const results = await this.getResults(FilterBox.Instance.getFinalQuery(this._searchString), -1); - const docs = results.map(doc => { + // const results = await this.getResults(FilterBox.Instance.getFinalQuery(this._searchString), -1); + await this.getResultsHelp(FilterBox.Instance.getFinalQuery(this._searchString)); + const docs = this._results.map(doc => { const isProto = Doc.GetT(doc, "isPrototype", "boolean", true); if (isProto) { return Doc.MakeDelegate(doc); @@ -295,23 +353,27 @@ export class SearchBox extends React.Component { this._numTotalResults = 0; this._startIndex = -1; this._endIndex = -1; + this._curRequest = undefined; } resultsScrolled = flow(function* (this: SearchBox, e?: React.UIEvent) { + console.log("_________________________________________________________________________________________________________") let scrollY = e ? e.currentTarget.scrollTop : 0; let buffer = 4; + console.log(`start before: ${this._startIndex}`); let startIndex = Math.floor(Math.max(0, scrollY / 70 - buffer)); + console.log(`end before: ${this._endIndex}`); let endIndex = Math.ceil(Math.min(this._numTotalResults - 1, startIndex + (560 / 70) + buffer)); if (startIndex === this._startIndex && endIndex === this._endIndex) { + console.log("returning") return; } - console.log("_________________________________________________________________________________________________________") console.log(`START: ${startIndex}`); console.log(`END: ${endIndex}`); - this._startIndex = startIndex; - this._endIndex = endIndex; + this._startIndex = startIndex === -1 ? 0 : startIndex; + this._endIndex = endIndex === -1 ? 12 : endIndex; if (this._numTotalResults === 0 && this._openNoResults) { this._visibleElements = [
No Search Results
]; @@ -341,17 +403,25 @@ export class SearchBox extends React.Component { let result: Doc | undefined = undefined; if (i >= this._results.length) { // _________________________________________________________________________________________________ - let results: Doc[] = yield this.getResults(this._searchString, i + 1 - this._results.length); - if (results.length !== 0) { - runInAction(() => { - this._results.push(...results); - result = this._results[i]; - if (result) { - this._visibleElements[i] = ; - this._isSearch[i] = "search"; - } - }); + // let results: Doc[] = yield this.getResults(this._searchString, i + 1 - this._results.length); + + // this updates this._results + yield this.getResultsHelp(this._searchString); + result = this._results[i]; + if (result) { + this._visibleElements[i] = ; + this._isSearch[i] = "search"; } + // if (results.length !== 0) { + // runInAction(() => { + // // this._results.push(...results); + // result = this._results[i]; + // if (result) { + // this._visibleElements[i] = ; + // this._isSearch[i] = "search"; + // } + // }); + // } // _________________________________________________________________________________________________ } else { -- cgit v1.2.3-70-g09d2 From e289ffead09b091fdb40aab47ea4d04ae5935455 Mon Sep 17 00:00:00 2001 From: monikahedman Date: Fri, 12 Jul 2019 15:28:34 -0400 Subject: things almost working yeet yeet --- src/client/views/search/SearchBox.tsx | 190 ++++++++++------------------------ 1 file changed, 54 insertions(+), 136 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 0816bb9de..8e5d317f0 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -16,6 +16,8 @@ import { SearchUtil } from '../../util/SearchUtil'; import { RouteStore } from '../../../server/RouteStore'; import { FilterBox } from './FilterBox'; import { start } from 'repl'; +import { getForkTsCheckerWebpackPluginHooks } from 'fork-ts-checker-webpack-plugin/lib/hooks'; +import { faThumbsDown } from '@fortawesome/free-regular-svg-icons'; @observer export class SearchBox extends React.Component { @@ -32,7 +34,7 @@ export class SearchBox extends React.Component { private _isSearch: ("search" | "placeholder" | undefined)[] = []; private _currentIndex = 0; - private _numTotalResults = 0; + private _numTotalResults = -1; private _startIndex = -1; private _endIndex = -1; private _fetchedIndices: number[] = [0]; @@ -40,7 +42,7 @@ export class SearchBox extends React.Component { static Instance: SearchBox; private _maxSearchIndex: number = 0; - private _curRequest: Promise | undefined = undefined; + private _curRequest?: Promise = undefined; constructor(props: any) { super(props); @@ -67,7 +69,7 @@ export class SearchBox extends React.Component { this._results = []; this._visibleElements = []; this._currentIndex = 0; - this._numTotalResults = 0; + this._numTotalResults = -1; this._startIndex = -1; this._endIndex = -1; this._curRequest = undefined; @@ -121,6 +123,7 @@ export class SearchBox extends React.Component { this._currentIndex = 0; this._startIndex = 0; this._endIndex = 12; + this._results = []; // this._curRequest = undefined; // if (this._curRequest !== undefined) { // this._curRequest.then(() => { @@ -129,6 +132,7 @@ export class SearchBox extends React.Component { // } this._maxSearchIndex = 0; + this._numTotalResults = -1; // results = await this.getResultsHelp(query); await this.getResultsHelp(query); @@ -151,144 +155,58 @@ export class SearchBox extends React.Component { // let buffer = 4; // let maxDisplayIndex: number = this._endIndex + buffer; - console.log(`end index: ${this._endIndex}`) - console.log(this._results.length) + // console.log(`end index: ${this._endIndex}`) + // console.log(this._results.length) + + while (this._results.length < this._endIndex && (this._numTotalResults === -1 || this._maxSearchIndex < this._numTotalResults)) { + console.log("looping"); + //start at max search index, get 10, add 10 to max search index + // const { docs, numFound } = await SearchUtil.Search(query, true, this._maxSearchIndex, 10); + + // happens at the beginning + // am i gonna need this? + // if (numFound !== this._numTotalResults && this._numTotalResults === 0) { + // this._numTotalResults = numFound; + // } - while (this._results.length < this._endIndex) { - console.log("looping") - if (this._curRequest === undefined) { - //start at max search index, get 10, add 10 to max search index - // const { docs, numFound } = await SearchUtil.Search(query, true, this._maxSearchIndex, 10); + let prom: Promise; + if (this._curRequest) { + prom = this._curRequest; + return; + } else { + prom = SearchUtil.Search(query, true, this._maxSearchIndex, 10); + this._maxSearchIndex += 10; + } + prom.then(action((res: SearchUtil.DocSearchResult) => { // happens at the beginning - // am i gonna need this? - // if (numFound !== this._numTotalResults && this._numTotalResults === 0) { - // this._numTotalResults = numFound; - // } + if (res.numFound !== this._numTotalResults && this._numTotalResults === -1) { + this._numTotalResults = res.numFound; + } - this._curRequest = SearchUtil.Search(query, true, this._maxSearchIndex, 10); - this._maxSearchIndex += 10; + let filteredDocs = FilterBox.Instance.filterDocsByType(res.docs); + this._results.push(...filteredDocs); - this._curRequest.then((res: SearchUtil.DocSearchResult) => { + console.log(this._results); + if (prom === this._curRequest) { + this._curRequest = undefined; + } + console.log("setting to undefined"); + })); - // happens at the beginning - if (res.numFound !== this._numTotalResults && this._numTotalResults === 0) { - this._numTotalResults = res.numFound; - } - let filteredDocs = FilterBox.Instance.filterDocsByType(res.docs); - this._results.push(...filteredDocs); - console.log(this._results) - this._curRequest = undefined; - console.log("setting to undefined") - }); + this._curRequest = prom; - //deals with if there are fewer results than can be scrolled through - // if (this._numTotalResults < this._endIndex) { - // break; - // } - } + await prom; + + //deals with if there are fewer results than can be scrolled through + // if (this._numTotalResults < this._endIndex) { + // break; + // } } } - // @action - // getResults = async (query: string, count: number) => { - // let resDocs = []; - // // count is total number of documents to be shown (i believe) - // console.log(`Count: ${count}`); - // while (resDocs.length < count) { - // let index = count === -1 ? undefined : this._currentIndex; - // let num = count === -1 ? undefined : Math.min(this._numTotalResults - this._currentIndex + 1, this._maxNum); - // // num found has to be the number of docs before filtering happens - this is the total num - // const { docs, numFound } = await SearchUtil.Search(query, true, index, num); - - // let filteredDocs = FilterBox.Instance.filterDocsByType(docs); - - // // accounts for the fact that there may be fewer documents than the max that are returned - // count = Math.min(numFound, count); - - // // happens at the beginning - // if (numFound !== this._numTotalResults && this._numTotalResults === 0) { - // console.log(`Total: ${numFound}`); - // this._numTotalResults = numFound; - // } - - // // if (filteredDocs.length < docs.length) { - // // this._numResults -= docs.length - filteredDocs.length; - // // console.log(`New Total: ${this._numResults}`); - // // } - // resDocs.push(...filteredDocs); - - // this._currentIndex += docs.length; - - // console.log(`ResDocs: ${resDocs.length}`); - // console.log(`CurrIndex: ${this._currentIndex}`); - // } - // // console.log(this.getResults2(query, count, [])); - // return resDocs; - // } - - // @action - // getResults2 = async (query: string, count: number, docs: Doc[]) => { - // console.log("results 2") - // let buffer = 4; - // // let goalIndex = this._endIndex + count; - // // let bottomBound = Math.floor(goalIndex / 10) * 10; - // let tempIndex = this._currentIndex; - // let goalNum = this._endIndex + buffer; - // let resDocs: Doc[] = docs; - - // // let topBound = bottomBound - 10; - // // let unfilteredDocs: Doc[]; - // // let unfilteredFound: number; - // // means this has already been fetched - // // if (this._fetchedIndices.includes(topBound)) { - // // return; - // // } - - // let index = count <= 0 ? undefined : this._currentIndex; - // if (index) { - // let topBound = Math.ceil(index / 10) * 10; - // if (this._fetchedIndices.includes(topBound)) { - // return; - // } - // let startIndex = this._fetchedIndices[this._fetchedIndices.length - 1]; - // let endIndex = startIndex + 10; - // this._fetchedIndices.push(endIndex); - // console.log(this._fetchedIndices) - // let prom: Promise = SearchUtil.Search(query, true, index, 10); - - // prom.then((res: SearchUtil.DocSearchResult) => { - // count = Math.min(res.numFound, count); - // console.log(res.docs); - // let filteredDocs = FilterBox.Instance.filterDocsByType(res.docs); - - // if (res.numFound !== this._numTotalResults && this._numTotalResults === 0) { - // this._numTotalResults = res.numFound; - // } - - // resDocs.push(...filteredDocs); - - // this._currentIndex += res.docs.length; - - // if (resDocs.length <= count) { - // runInAction(() => { - // return this.getResults2(query, count, resDocs); - // }); - // } - // else { - // return resDocs; - // } - // // console.log(tempIndex); - // console.log(resDocs.length); - // }) - - // } - - - // } - collectionRef = React.createRef(); startDragCollection = async () => { // const results = await this.getResults(FilterBox.Instance.getFinalQuery(this._searchString), -1); @@ -350,7 +268,7 @@ export class SearchBox extends React.Component { this._results = []; this._visibleElements = []; this._currentIndex = 0; - this._numTotalResults = 0; + this._numTotalResults = -1; this._startIndex = -1; this._endIndex = -1; this._curRequest = undefined; @@ -365,10 +283,10 @@ export class SearchBox extends React.Component { console.log(`end before: ${this._endIndex}`); let endIndex = Math.ceil(Math.min(this._numTotalResults - 1, startIndex + (560 / 70) + buffer)); - if (startIndex === this._startIndex && endIndex === this._endIndex) { - console.log("returning") - return; - } + // if (startIndex === this._startIndex && endIndex === this._endIndex && this._results.length > this._endIndex) { + // console.log("returning") + // return; + // } console.log(`START: ${startIndex}`); console.log(`END: ${endIndex}`); @@ -384,9 +302,9 @@ export class SearchBox extends React.Component { // 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); + this._visibleElements = Array(this._numTotalResults === -1 ? 0 : this._numTotalResults); // indicates if things are placeholders - this._isSearch = Array(this._numTotalResults); + this._isSearch = Array(this._numTotalResults === -1 ? 0 : this._numTotalResults); } for (let i = 0; i < this._numTotalResults; i++) { -- cgit v1.2.3-70-g09d2 From 8c82a0fb1310429a973b536d5e0c25c3749d7e14 Mon Sep 17 00:00:00 2001 From: monikahedman Date: Fri, 12 Jul 2019 17:03:59 -0400 Subject: send help --- deploy/index.html | 1 - src/client/views/search/FilterBox.tsx | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src/client/views/search') diff --git a/deploy/index.html b/deploy/index.html index f4a019b71..532b995f8 100644 --- a/deploy/index.html +++ b/deploy/index.html @@ -6,7 +6,6 @@ - diff --git a/src/client/views/search/FilterBox.tsx b/src/client/views/search/FilterBox.tsx index 4c74c0413..5aa3e9509 100644 --- a/src/client/views/search/FilterBox.tsx +++ b/src/client/views/search/FilterBox.tsx @@ -239,6 +239,9 @@ export class FilterBox extends React.Component { @action filterDocsByType(docs: Doc[]) { + if (this._icons.length === 9) { + return docs; + } let finalDocs: Doc[] = []; docs.forEach(doc => { let layoutresult = Cast(doc.type, "string"); -- cgit v1.2.3-70-g09d2 From 00a9a169679baa011c66b28152ff27dec2532907 Mon Sep 17 00:00:00 2001 From: monikahedman Date: Fri, 12 Jul 2019 18:15:31 -0400 Subject: end of day 7/12 --- src/client/views/search/SearchBox.tsx | 175 +++++++++++----------------------- 1 file changed, 54 insertions(+), 121 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 8e5d317f0..e5280fe8c 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -30,14 +30,12 @@ export class SearchBox extends React.Component { //temp @observable public _maxNum: number = 10; @observable private _visibleElements: JSX.Element[] = []; - @observable private _scrollY: number = 0; + // @observable private _sc rollY: number = 0; private _isSearch: ("search" | "placeholder" | undefined)[] = []; - private _currentIndex = 0; private _numTotalResults = -1; private _startIndex = -1; private _endIndex = -1; - private _fetchedIndices: number[] = [0]; static Instance: SearchBox; @@ -68,7 +66,6 @@ export class SearchBox extends React.Component { this._openNoResults = false; this._results = []; this._visibleElements = []; - this._currentIndex = 0; this._numTotalResults = -1; this._startIndex = -1; this._endIndex = -1; @@ -97,120 +94,81 @@ export class SearchBox extends React.Component { @action submitSearch = async () => { - let query = this._searchString; // searchbox gets query - let results: Doc[]; - + let query = this._searchString; query = FilterBox.Instance.getFinalQuery(query); - - // if (this._curRequest !== undefined) { - // this._curRequest.then(() => { - // this._curRequest = undefined; - // this._results = []; - // }); - // } - - // this._results = []; + this._results = []; + this._isSearch = []; + this._visibleElements = []; //if there is no query there should be no result if (query === "") { - // results = []; return; } else { - //gets json result into a list of documents that can be used - //these are filtered by type - // this._results = []; - this._currentIndex = 0; this._startIndex = 0; this._endIndex = 12; - this._results = []; - // this._curRequest = undefined; - // if (this._curRequest !== undefined) { - // this._curRequest.then(() => { - // this._curRequest = undefined; - // }); - // } - this._maxSearchIndex = 0; this._numTotalResults = -1; - - // results = await this.getResultsHelp(query); - await this.getResultsHelp(query); + await this.getResults(query); } runInAction(() => { this._resultsOpen = true; - // this._results = results; this._openNoResults = true; this.resultsScrolled(); }); - } - getResultsHelp = async (query: string) => { - // docs length = this._results.length --> number of docs that are shown (after filtering) - // stops looking once this._results.length >= maxDisplayIndex - // max search index = number of results looked through in solr (solr index) --> increments of 10 - // max display index = number of documents that SHOULD be shown (should include buffer), this._endIndex + buffer (= 4) - // currentRequest = promise | undefined, if undefined, can run and look for more. If not undefined, then there is a request in progress and it cannot look for more yet - - // let buffer = 4; - // let maxDisplayIndex: number = this._endIndex + buffer; - // console.log(`end index: ${this._endIndex}`) - // console.log(this._results.length) - - while (this._results.length < this._endIndex && (this._numTotalResults === -1 || this._maxSearchIndex < this._numTotalResults)) { - console.log("looping"); - //start at max search index, get 10, add 10 to max search index - // const { docs, numFound } = await SearchUtil.Search(query, true, this._maxSearchIndex, 10); - - // happens at the beginning - // am i gonna need this? - // if (numFound !== this._numTotalResults && this._numTotalResults === 0) { - // this._numTotalResults = numFound; - // } - - let prom: Promise; - if (this._curRequest) { - prom = this._curRequest; - return; - } else { - prom = SearchUtil.Search(query, true, this._maxSearchIndex, 10); - this._maxSearchIndex += 10; - } - prom.then(action((res: SearchUtil.DocSearchResult) => { + console.log(this._results) + } - // happens at the beginning - if (res.numFound !== this._numTotalResults && this._numTotalResults === -1) { - this._numTotalResults = res.numFound; - } + getResults = async (query: string, all: boolean = false) => { - let filteredDocs = FilterBox.Instance.filterDocsByType(res.docs); - this._results.push(...filteredDocs); + if (all) { + // let { numFound, docs } = await SearchUtil.Search(query, true, this._maxSearchIndex, 100000); + let prom: Promise = SearchUtil.Search(query, true, 0, 100000); - console.log(this._results); - if (prom === this._curRequest) { - this._curRequest = undefined; + prom.then(({ docs, numFound }) => { + this._results = docs; + }) + } + else { + while (this._results.length <= this._endIndex && (this._numTotalResults === -1 || this._maxSearchIndex < this._numTotalResults)) { + + let prom: Promise; + if (this._curRequest) { + prom = this._curRequest; + return; + } else { + prom = SearchUtil.Search(query, true, this._maxSearchIndex, 10); + this._maxSearchIndex += 10; } - console.log("setting to undefined"); - })); + prom.then(action((res: SearchUtil.DocSearchResult) => { + // happens at the beginning + if (res.numFound !== this._numTotalResults && this._numTotalResults === -1) { + this._numTotalResults = res.numFound; + } + let filteredDocs = FilterBox.Instance.filterDocsByType(res.docs); + this._results.push(...filteredDocs); - this._curRequest = prom; + if (prom === this._curRequest) { + this._curRequest = undefined; + } + })); - await prom; + this._curRequest = prom; - //deals with if there are fewer results than can be scrolled through - // if (this._numTotalResults < this._endIndex) { - // break; - // } + await prom; + } } } collectionRef = React.createRef(); startDragCollection = async () => { - // const results = await this.getResults(FilterBox.Instance.getFinalQuery(this._searchString), -1); - await this.getResultsHelp(FilterBox.Instance.getFinalQuery(this._searchString)); + await this.getResults(FilterBox.Instance.getFinalQuery(this._searchString), true); + console.log(this._results) + // if (res !== undefined) { const docs = this._results.map(doc => { const isProto = Doc.GetT(doc, "isPrototype", "boolean", true); if (isProto) { @@ -244,6 +202,7 @@ export class SearchBox extends React.Component { } } return Docs.FreeformDocument(docs, { width: 400, height: 400, panX: 175, panY: 175, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` }); + // } } @action.bound @@ -257,7 +216,6 @@ export class SearchBox extends React.Component { @action.bound closeSearch = () => { - console.log("closing search") FilterBox.Instance.closeFilter(); this.closeResults(); } @@ -267,7 +225,6 @@ export class SearchBox extends React.Component { this._resultsOpen = false; this._results = []; this._visibleElements = []; - this._currentIndex = 0; this._numTotalResults = -1; this._startIndex = -1; this._endIndex = -1; @@ -275,21 +232,11 @@ export class SearchBox extends React.Component { } resultsScrolled = flow(function* (this: SearchBox, e?: React.UIEvent) { - console.log("_________________________________________________________________________________________________________") let scrollY = e ? e.currentTarget.scrollTop : 0; let buffer = 4; - console.log(`start before: ${this._startIndex}`); let startIndex = Math.floor(Math.max(0, scrollY / 70 - buffer)); - console.log(`end before: ${this._endIndex}`); let endIndex = Math.ceil(Math.min(this._numTotalResults - 1, startIndex + (560 / 70) + buffer)); - // if (startIndex === this._startIndex && endIndex === this._endIndex && this._results.length > this._endIndex) { - // console.log("returning") - // return; - // } - console.log(`START: ${startIndex}`); - console.log(`END: ${endIndex}`); - this._startIndex = startIndex === -1 ? 0 : startIndex; this._endIndex = endIndex === -1 ? 12 : endIndex; @@ -298,6 +245,10 @@ export class SearchBox extends React.Component { 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) { @@ -320,27 +271,12 @@ export class SearchBox extends React.Component { if (this._isSearch[i] !== "search") { let result: Doc | undefined = undefined; if (i >= this._results.length) { - // _________________________________________________________________________________________________ - // let results: Doc[] = yield this.getResults(this._searchString, i + 1 - this._results.length); - - // this updates this._results - yield this.getResultsHelp(this._searchString); - result = this._results[i]; + this.getResults(this._searchString); + if (i < this._results.length) result = this._results[i]; if (result) { this._visibleElements[i] = ; this._isSearch[i] = "search"; } - // if (results.length !== 0) { - // runInAction(() => { - // // this._results.push(...results); - // result = this._results[i]; - // if (result) { - // this._visibleElements[i] = ; - // this._isSearch[i] = "search"; - // } - // }); - // } - // _________________________________________________________________________________________________ } else { result = this._results[i]; @@ -352,6 +288,10 @@ export class SearchBox extends React.Component { } } } + if (this._maxSearchIndex >= this._numTotalResults) { + this._visibleElements.length = this._results.length; + this._isSearch.length = this._results.length; + } }); render() { @@ -367,15 +307,8 @@ export class SearchBox extends React.Component {
- {/* {(this._results.length !== 0) ? ( - this._results.map(result => ) - ) : - this._openNoResults ? (
No Search Results
) : null} */} {this._visibleElements}
- {/*
- -
*/}
); } -- cgit v1.2.3-70-g09d2 From d75d951a863103568f93ab9b04259d07b9668b47 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Fri, 12 Jul 2019 19:25:20 -0400 Subject: Various small changes/fixes --- src/client/views/MainView.tsx | 8 +++++--- src/client/views/collections/CollectionVideoView.tsx | 2 +- src/client/views/nodes/VideoBox.tsx | 6 ++++-- src/client/views/search/SearchItem.tsx | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index f0e11a480..614b9cce7 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -1,5 +1,5 @@ import { IconName, library } from '@fortawesome/fontawesome-svg-core'; -import { faArrowDown, faArrowUp, faClone, faCheck, faCommentAlt, faCut, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faPortrait, faMusic, faObjectGroup, faPenNib, faRedoAlt, faTable, faThumbtack, faTree, faUndoAlt } from '@fortawesome/free-solid-svg-icons'; +import { faArrowDown, faArrowUp, faClone, faCheck, faCommentAlt, faCut, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faPortrait, faMusic, faObjectGroup, faPenNib, faRedoAlt, faTable, faThumbtack, faTree, faUndoAlt, faCat } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, configure, observable, runInAction, reaction, trace } from 'mobx'; import { observer } from 'mobx-react'; @@ -38,6 +38,7 @@ import { PresentationView } from './presentationview/PresentationView'; import { PreviewCursor } from './PreviewCursor'; import { FilterBox } from './search/FilterBox'; import { CollectionTreeView } from './collections/CollectionTreeView'; +import { ClientUtils } from '../util/ClientUtils'; @observer export class MainView extends React.Component { @@ -111,6 +112,7 @@ export class MainView extends React.Component { library.add(faFont); library.add(faExclamation); library.add(faPortrait); + library.add(faCat); library.add(faFilePdf); library.add(faObjectGroup); library.add(faTable); @@ -378,11 +380,11 @@ export class MainView extends React.Component { let addImportCollectionNode = action(() => Docs.Create.DirectoryImportDocument({ title: "Directory Import", width: 400, height: 400 })); let btns: [React.RefObject, IconName, string, () => Doc][] = [ - [React.createRef(), "portrait", "Add Cat Image", addImageNode], [React.createRef(), "object-group", "Add Collection", addColNode], // [React.createRef(), "clone", "Add Docking Frame", addDockingNode], [React.createRef(), "arrow-up", "Import Directory", addImportCollectionNode], ]; + if (!ClientUtils.RELEASE) btns.unshift([React.createRef(), "cat", "Add Cat Image", addImageNode]); return < div id="add-nodes-menu" style={{ left: this.flyoutWidth + 5 }} > @@ -399,7 +401,7 @@ export class MainView extends React.Component {
)} -
  • +
  • diff --git a/src/client/views/search/SearchItem.scss b/src/client/views/search/SearchItem.scss index fa4c9cb38..04ebf2714 100644 --- a/src/client/views/search/SearchItem.scss +++ b/src/client/views/search/SearchItem.scss @@ -73,34 +73,38 @@ -o-transition: opacity 0.2s ease-in-out; transition: opacity 0.2s ease-in-out; } - } - .link-container.item:hover { - width: 70px; } - .link-container.item:hover .link-count { - opacity: 0; - } + // .link-container.item:hover { + // width: 70px; + // } + + // .link-container.item:hover .link-count { + // opacity: 0; + // } + + // .link-container.item:hover .link-extended { + // opacity: 1; + // } - .link-container.item:hover .link-extended { - opacity: 1; - } - .icon-icons { - width:50px + width: 50px } + .icon-live { - width:175px; + width: 175px; } - .icon-icons, .icon-live { - height:50px; - margin:auto; + .icon-icons, + .icon-live { + height: 50px; + margin: auto; overflow: hidden; + .search-type { display: inline-block; - width:100%; + width: 100%; position: absolute; justify-content: center; align-items: center; @@ -112,10 +116,11 @@ overflow: hidden; img { - width:100% !important; - height:auto !important; + width: 100% !important; + height: auto !important; } } + .search-type:hover+.search-label { opacity: 1; } @@ -134,16 +139,18 @@ } .icon-live:hover { - height:175px; + height: 175px; + .pdfBox-cont { img { - width:100% !important; + width: 100% !important; } } } } + .search-info:hover { - width:60%; + width: 60%; } } } @@ -176,12 +183,15 @@ } } + .search-overview:hover { z-index: 1; } + .collection { - display:flex; + display: flex; } + .collection-item { - width:35px; + width: 35px; } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 865c144e7d883ee1c15ee2a59fb261e63958f5a8 Mon Sep 17 00:00:00 2001 From: monikahedman Date: Sun, 14 Jul 2019 14:11:29 -0400 Subject: link count should work soon --- src/client/views/search/SearchItem.scss | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/SearchItem.scss b/src/client/views/search/SearchItem.scss index 04ebf2714..140ced8e5 100644 --- a/src/client/views/search/SearchItem.scss +++ b/src/client/views/search/SearchItem.scss @@ -76,17 +76,17 @@ } - // .link-container.item:hover { - // width: 70px; - // } + .link-container.item:hover { + width: 70px; + } - // .link-container.item:hover .link-count { - // opacity: 0; - // } + .link-container.item:hover .link-count { + opacity: 0; + } - // .link-container.item:hover .link-extended { - // opacity: 1; - // } + .link-container.item:hover .link-extended { + opacity: 1; + } .icon-icons { width: 50px -- cgit v1.2.3-70-g09d2 From b5740401b027c372edb5bbf465f91abfda663705 Mon Sep 17 00:00:00 2001 From: monikahedman Date: Sun, 14 Jul 2019 15:00:47 -0400 Subject: small ui changes done --- src/client/views/search/FilterBox.tsx | 2 +- src/client/views/search/SearchBox.tsx | 2 +- src/client/views/search/SearchItem.scss | 13 +++++++++---- src/client/views/search/SearchItem.tsx | 4 ++-- 4 files changed, 13 insertions(+), 8 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/FilterBox.tsx b/src/client/views/search/FilterBox.tsx index c6c18f9b4..58a873ced 100644 --- a/src/client/views/search/FilterBox.tsx +++ b/src/client/views/search/FilterBox.tsx @@ -260,7 +260,7 @@ export class FilterBox extends React.Component { @action.bound handleWordQueryChange = () => { this._basicWordStatus = !this._basicWordStatus; } - @action + @action.bound getBasicWordStatus() { return this._basicWordStatus; } @action.bound diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index cddc56a8a..121abf973 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -170,7 +170,7 @@ export class SearchBox extends React.Component { return (
    - + {
    {StrCast(this.props.doc.title)}
    -
    {this.DocumentIcon}
    -
    {this.props.doc.type}
    +
    {this.DocumentIcon}
    +
    {this.props.doc.type ? this.props.doc.type : "Other"}
    {this.linkCount}
    -- cgit v1.2.3-70-g09d2 From 2575564d70828820521074455383e940d521cca8 Mon Sep 17 00:00:00 2001 From: monikahedman Date: Sun, 14 Jul 2019 16:03:22 -0400 Subject: yeeeee --- src/client/views/search/SearchBox.scss | 3 +- src/client/views/search/SearchBox.tsx | 73 ++++++++++++++-------------------- 2 files changed, 32 insertions(+), 44 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/SearchBox.scss b/src/client/views/search/SearchBox.scss index 2a27bbe62..4c78b2682 100644 --- a/src/client/views/search/SearchBox.scss +++ b/src/client/views/search/SearchBox.scss @@ -46,7 +46,8 @@ display: flex; flex-direction: column; margin-right: 72px; - height: 560px; + height: auto; + max-height: 560px; overflow: hidden; overflow-y: auto; diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index e5280fe8c..47f951f42 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -26,11 +26,7 @@ export class SearchBox extends React.Component { @observable private _resultsOpen: boolean = false; @observable private _results: Doc[] = []; @observable private _openNoResults: boolean = false; - @observable public _pageNum: number = 0; - //temp - @observable public _maxNum: number = 10; @observable private _visibleElements: JSX.Element[] = []; - // @observable private _sc rollY: number = 0; private _isSearch: ("search" | "placeholder" | undefined)[] = []; private _numTotalResults = -1; @@ -117,59 +113,50 @@ export class SearchBox extends React.Component { this._openNoResults = true; this.resultsScrolled(); }); + } - console.log(this._results) + getAllResults = async (query: string) => { + return SearchUtil.Search(query, true, 0, 10000000); } - getResults = async (query: string, all: boolean = false) => { + getResults = async (query: string) => { - if (all) { - // let { numFound, docs } = await SearchUtil.Search(query, true, this._maxSearchIndex, 100000); - let prom: Promise = SearchUtil.Search(query, true, 0, 100000); + while (this._results.length <= this._endIndex && (this._numTotalResults === -1 || this._maxSearchIndex < this._numTotalResults)) { - prom.then(({ docs, numFound }) => { - this._results = docs; - }) - } - else { - while (this._results.length <= this._endIndex && (this._numTotalResults === -1 || this._maxSearchIndex < this._numTotalResults)) { - - let prom: Promise; - if (this._curRequest) { - prom = this._curRequest; - return; - } else { - prom = SearchUtil.Search(query, true, this._maxSearchIndex, 10); - this._maxSearchIndex += 10; - } - prom.then(action((res: SearchUtil.DocSearchResult) => { + let prom: Promise; + if (this._curRequest) { + prom = this._curRequest; + return; + } else { + prom = SearchUtil.Search(query, true, this._maxSearchIndex, 10); + this._maxSearchIndex += 10; + } + prom.then(action((res: SearchUtil.DocSearchResult) => { - // happens at the beginning - if (res.numFound !== this._numTotalResults && this._numTotalResults === -1) { - this._numTotalResults = res.numFound; - } + // happens at the beginning + if (res.numFound !== this._numTotalResults && this._numTotalResults === -1) { + this._numTotalResults = res.numFound; + } - let filteredDocs = FilterBox.Instance.filterDocsByType(res.docs); - this._results.push(...filteredDocs); + let filteredDocs = FilterBox.Instance.filterDocsByType(res.docs); + this._results.push(...filteredDocs); - if (prom === this._curRequest) { - this._curRequest = undefined; - } - })); + if (prom === this._curRequest) { + this._curRequest = undefined; + } + })); - this._curRequest = prom; + this._curRequest = prom; - await prom; - } + await prom; } } collectionRef = React.createRef(); startDragCollection = async () => { - await this.getResults(FilterBox.Instance.getFinalQuery(this._searchString), true); - console.log(this._results) - // if (res !== undefined) { - const docs = this._results.map(doc => { + let res = await this.getAllResults(FilterBox.Instance.getFinalQuery(this._searchString)); + // console.log(this._results) + const docs = res.docs.map(doc => { const isProto = Doc.GetT(doc, "isPrototype", "boolean", true); if (isProto) { return Doc.MakeDelegate(doc); @@ -202,7 +189,7 @@ export class SearchBox extends React.Component { } } return Docs.FreeformDocument(docs, { width: 400, height: 400, panX: 175, panY: 175, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` }); - // } + } @action.bound -- cgit v1.2.3-70-g09d2 From dcb7b3ec59b8458fc074656067b35e9068d5e3de Mon Sep 17 00:00:00 2001 From: monikahedman Date: Sun, 14 Jul 2019 17:08:15 -0400 Subject: fixed --- src/client/views/search/SearchBox.scss | 2 - src/client/views/search/SearchBox.tsx | 342 ++++++++++++++++++++++++++------- 2 files changed, 277 insertions(+), 67 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/SearchBox.scss b/src/client/views/search/SearchBox.scss index 4c78b2682..1ec89ed2b 100644 --- a/src/client/views/search/SearchBox.scss +++ b/src/client/views/search/SearchBox.scss @@ -46,9 +46,7 @@ display: flex; flex-direction: column; margin-right: 72px; - height: auto; max-height: 560px; - overflow: hidden; overflow-y: auto; .no-result { diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 5989e49bd..b9ada9677 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -1,26 +1,111 @@ import * as React from 'react'; -import { observer } from 'mobx-react'; -import { observable, action, runInAction, flow } from 'mobx'; + +import { + observer +} + + from 'mobx-react'; + +import { + observable, + action, + runInAction, + flow, + computed +} + + from 'mobx'; import "./SearchBox.scss"; import "./FilterBox.scss"; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { SetupDrag } from '../../util/DragManager'; -import { Docs } from '../../documents/Documents'; -import { NumCast } from '../../../new_fields/Types'; -import { Doc } from '../../../new_fields/Doc'; -import { SearchItem } from './SearchItem'; -import { DocServer } from '../../DocServer'; + +import { + FontAwesomeIcon +} + + from '@fortawesome/react-fontawesome'; + +import { + SetupDrag +} + + from '../../util/DragManager'; + +import { + Docs +} + + from '../../documents/Documents'; + +import { + NumCast +} + + from '../../../new_fields/Types'; + +import { + Doc +} + + from '../../../new_fields/Doc'; + +import { + SearchItem +} + + from './SearchItem'; + +import { + DocServer +} + + from '../../DocServer'; import * as rp from 'request-promise'; -import { Id } from '../../../new_fields/FieldSymbols'; -import { SearchUtil } from '../../util/SearchUtil'; -import { RouteStore } from '../../../server/RouteStore'; -import { FilterBox } from './FilterBox'; -import { start } from 'repl'; -import { getForkTsCheckerWebpackPluginHooks } from 'fork-ts-checker-webpack-plugin/lib/hooks'; -import { faThumbsDown } from '@fortawesome/free-regular-svg-icons'; -@observer -export class SearchBox extends React.Component { +import { + Id +} + + from '../../../new_fields/FieldSymbols'; + +import { + SearchUtil +} + + from '../../util/SearchUtil'; + +import { + RouteStore +} + + from '../../../server/RouteStore'; + +import { + FilterBox +} + + from './FilterBox'; + +import { + start +} + + from 'repl'; + +import { + getForkTsCheckerWebpackPluginHooks +} + + from 'fork-ts-checker-webpack-plugin/lib/hooks'; + +import { + faThumbsDown +} + + from '@fortawesome/free-regular-svg-icons'; +import * as $ from 'jquery'; + + +@observer export class SearchBox extends React.Component { @observable private _searchString: string = ""; @observable private _resultsOpen: boolean = false; @@ -45,18 +130,19 @@ export class SearchBox extends React.Component { this.resultsScrolled = this.resultsScrolled.bind(this); } - @action - getViews = async (doc: Doc) => { + @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) { + @action.bound onChange(e: React.ChangeEvent) { this._searchString = e.target.value; this._openNoResults = false; @@ -69,27 +155,37 @@ export class SearchBox extends React.Component { this._maxSearchIndex = 0; } - enter = (e: React.KeyboardEvent) => { if (e.key === "Enter") { this.submitSearch(); } } + enter = (e: React.KeyboardEvent) => { + if (e.key === "Enter") { + this.submitSearch(); + } + } public static async convertDataUri(imageUri: string, returnedFilename: string) { try { let posting = DocServer.prepend(RouteStore.dataUriToImage); + const returnedUri = await rp.post(posting, { body: { uri: imageUri, name: returnedFilename - }, + } + + , json: true, - }); + } + + ); return returnedUri; - } catch (e) { + } + + catch (e) { console.log(e); } } - @action - submitSearch = async () => { + @action submitSearch = async () => { let query = this._searchString; query = FilterBox.Instance.getFinalQuery(query); this._results = []; @@ -100,6 +196,7 @@ export class SearchBox extends React.Component { if (query === "") { return; } + else { this._startIndex = 0; this._endIndex = 12; @@ -112,7 +209,9 @@ export class SearchBox extends React.Component { this._resultsOpen = true; this._openNoResults = true; this.resultsScrolled(); - }); + } + + ); } getAllResults = async (query: string) => { @@ -124,13 +223,17 @@ export class SearchBox extends React.Component { while (this._results.length <= this._endIndex && (this._numTotalResults === -1 || this._maxSearchIndex < this._numTotalResults)) { let prom: Promise; + if (this._curRequest) { prom = this._curRequest; return; - } else { + } + + else { prom = SearchUtil.Search(query, true, this._maxSearchIndex, 10); this._maxSearchIndex += 10; } + prom.then(action((res: SearchUtil.DocSearchResult) => { // happens at the beginning @@ -144,7 +247,9 @@ export class SearchBox extends React.Component { if (prom === this._curRequest) { this._curRequest = undefined; } - })); + } + + )); this._curRequest = prom; @@ -153,47 +258,67 @@ export class SearchBox extends React.Component { } collectionRef = React.createRef(); + startDragCollection = async () => { let res = await this.getAllResults(FilterBox.Instance.getFinalQuery(this._searchString)); + let filtered = FilterBox.Instance.filterDocsByType(res.docs); + // console.log(this._results) - const docs = res.docs.map(doc => { + const docs = filtered.map(doc => { const isProto = Doc.GetT(doc, "isPrototype", "boolean", true); + if (isProto) { return Doc.MakeDelegate(doc); - } else { + } + + else { return Doc.MakeAlias(doc); } - }); + } + + ); let x = 0; let y = 0; + for (const doc of docs) { 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) { + } + + else if (aspect > 0) { doc.width = size; doc.height = size * aspect; - } else { + } + + else { doc.width = size; doc.height = size; } + doc.zoomBasis = 1; x += 250; + if (x > 1000) { x = 0; y += 300; } } - return Docs.Create.FreeformDocument(docs, { width: 400, height: 400, panX: 175, panY: 175, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` }); + + return Docs.Create.FreeformDocument(docs, { + width: 400, height: 400, panX: 175, panY: 175, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` + } + + ); } - @action.bound - openSearch(e: React.PointerEvent) { + @action.bound openSearch(e: React.PointerEvent) { e.stopPropagation(); this._openNoResults = false; FilterBox.Instance.closeFilter(); @@ -201,14 +326,12 @@ export class SearchBox extends React.Component { FilterBox.Instance._pointerTime = e.timeStamp; } - @action.bound - closeSearch = () => { + @action.bound closeSearch = () => { FilterBox.Instance.closeFilter(); this.closeResults(); } - @action.bound - closeResults() { + @action.bound closeResults() { this._resultsOpen = false; this._results = []; this._visibleElements = []; @@ -245,59 +368,148 @@ export class SearchBox extends React.Component { this._isSearch = Array(this._numTotalResults === -1 ? 0 : this._numTotalResults); } - for (let i = 0; i < this._numTotalResults; i++) { + 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] =
    ; + + this._visibleElements[i] =
    ; } } + else { if (this._isSearch[i] !== "search") { let result: Doc | undefined = undefined; + if (i >= this._results.length) { this.getResults(this._searchString); if (i < this._results.length) result = this._results[i]; + if (result) { - this._visibleElements[i] = ; + this._visibleElements[i] = ; this._isSearch[i] = "search"; } } + else { result = this._results[i]; + if (result) { - this._visibleElements[i] = ; + 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() { + console.log(`res full $ { + this._numTotalResults <=8 + } + + `) return this._numTotalResults <= 8; + } + + @computed get resultHeight() { + return this._numTotalResults * 70; + } render() { - return ( -
    -
    - - - - - -
    -
    - {this._visibleElements} -
    -
    - ); + return (
    { + this._visibleElements + } + +
    ); } } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From f0e1eae76147d9c70309dcea54f6516622efca0f Mon Sep 17 00:00:00 2001 From: monikahedman Date: Sun, 14 Jul 2019 17:11:03 -0400 Subject: oops --- src/client/views/search/SearchBox.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index b9ada9677..8bf8e3bfa 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -442,11 +442,7 @@ import * as $ from 'jquery'; ); @computed get resFull() { - console.log(`res full $ { - this._numTotalResults <=8 - } - - `) return this._numTotalResults <= 8; + return this._numTotalResults <= 8; } @computed get resultHeight() { -- cgit v1.2.3-70-g09d2 From 44b91eacaab13eebaaa707f42670f01a736c5bba Mon Sep 17 00:00:00 2001 From: monikahedman Date: Sun, 14 Jul 2019 18:12:02 -0400 Subject: small changes --- src/client/views/search/SearchBox.tsx | 335 +++++++-------------------------- src/client/views/search/SearchItem.tsx | 2 +- src/server/Search.ts | 12 ++ 3 files changed, 85 insertions(+), 264 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 8bf8e3bfa..f5748d494 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -1,111 +1,28 @@ import * as React from 'react'; - -import { - observer -} - - from 'mobx-react'; - -import { - observable, - action, - runInAction, - flow, - computed -} - - from 'mobx'; +import { observer } from 'mobx-react'; +import { observable, action, runInAction, flow, computed } from 'mobx'; import "./SearchBox.scss"; import "./FilterBox.scss"; - -import { - FontAwesomeIcon -} - - from '@fortawesome/react-fontawesome'; - -import { - SetupDrag -} - - from '../../util/DragManager'; - -import { - Docs -} - - from '../../documents/Documents'; - -import { - NumCast -} - - from '../../../new_fields/Types'; - -import { - Doc -} - - from '../../../new_fields/Doc'; - -import { - SearchItem -} - - from './SearchItem'; - -import { - DocServer -} - - from '../../DocServer'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { SetupDrag } from '../../util/DragManager'; +import { Docs } from '../../documents/Documents'; +import { NumCast } from '../../../new_fields/Types'; +import { Doc } from '../../../new_fields/Doc'; +import { SearchItem } from './SearchItem'; +import { DocServer } from '../../DocServer'; import * as rp from 'request-promise'; - -import { - Id -} - - from '../../../new_fields/FieldSymbols'; - -import { - SearchUtil -} - - from '../../util/SearchUtil'; - -import { - RouteStore -} - - from '../../../server/RouteStore'; - -import { - FilterBox -} - - from './FilterBox'; - -import { - start -} - - from 'repl'; - -import { - getForkTsCheckerWebpackPluginHooks -} - - from 'fork-ts-checker-webpack-plugin/lib/hooks'; - -import { - faThumbsDown -} - - from '@fortawesome/free-regular-svg-icons'; +import { Id } from '../../../new_fields/FieldSymbols'; +import { SearchUtil } from '../../util/SearchUtil'; +import { RouteStore } from '../../../server/RouteStore'; +import { FilterBox } from './FilterBox'; +import { start } from 'repl'; +import { getForkTsCheckerWebpackPluginHooks } from 'fork-ts-checker-webpack-plugin/lib/hooks'; +import { faThumbsDown } from '@fortawesome/free-regular-svg-icons'; import * as $ from 'jquery'; -@observer export class SearchBox extends React.Component { +@observer +export class SearchBox extends React.Component { @observable private _searchString: string = ""; @observable private _resultsOpen: boolean = false; @@ -130,19 +47,18 @@ import * as $ from 'jquery'; this.resultsScrolled = this.resultsScrolled.bind(this); } - @action getViews = async (doc: Doc) => { + @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) { + @action.bound + onChange(e: React.ChangeEvent) { this._searchString = e.target.value; this._openNoResults = false; @@ -155,37 +71,27 @@ import * as $ from 'jquery'; this._maxSearchIndex = 0; } - enter = (e: React.KeyboardEvent) => { - if (e.key === "Enter") { - this.submitSearch(); - } - } + enter = (e: React.KeyboardEvent) => { if (e.key === "Enter") { this.submitSearch(); } } public static async convertDataUri(imageUri: string, returnedFilename: string) { try { let posting = DocServer.prepend(RouteStore.dataUriToImage); - const returnedUri = await rp.post(posting, { body: { uri: imageUri, name: returnedFilename - } - - , + }, json: true, - } - - ); + }); return returnedUri; - } - - catch (e) { + } catch (e) { console.log(e); } } - @action submitSearch = async () => { + @action + submitSearch = async () => { let query = this._searchString; query = FilterBox.Instance.getFinalQuery(query); this._results = []; @@ -196,7 +102,6 @@ import * as $ from 'jquery'; if (query === "") { return; } - else { this._startIndex = 0; this._endIndex = 12; @@ -209,9 +114,7 @@ import * as $ from 'jquery'; this._resultsOpen = true; this._openNoResults = true; this.resultsScrolled(); - } - - ); + }); } getAllResults = async (query: string) => { @@ -223,17 +126,13 @@ import * as $ from 'jquery'; while (this._results.length <= this._endIndex && (this._numTotalResults === -1 || this._maxSearchIndex < this._numTotalResults)) { let prom: Promise; - if (this._curRequest) { prom = this._curRequest; return; - } - - else { + } else { prom = SearchUtil.Search(query, true, this._maxSearchIndex, 10); this._maxSearchIndex += 10; } - prom.then(action((res: SearchUtil.DocSearchResult) => { // happens at the beginning @@ -247,9 +146,7 @@ import * as $ from 'jquery'; if (prom === this._curRequest) { this._curRequest = undefined; } - } - - )); + })); this._curRequest = prom; @@ -258,67 +155,48 @@ import * as $ from 'jquery'; } collectionRef = React.createRef(); - startDragCollection = async () => { let res = await this.getAllResults(FilterBox.Instance.getFinalQuery(this._searchString)); let 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 { + } else { return Doc.MakeAlias(doc); } - } - - ); + }); let x = 0; let y = 0; - for (const doc of docs) { 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) { + } else if (aspect > 0) { doc.width = size; doc.height = size * aspect; - } - - else { + } else { doc.width = size; doc.height = size; } - doc.zoomBasis = 1; x += 250; - if (x > 1000) { x = 0; y += 300; } } - - return Docs.Create.FreeformDocument(docs, { - width: 400, height: 400, panX: 175, panY: 175, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` - } - - ); + return Docs.Create.FreeformDocument(docs, { width: 400, height: 400, panX: 175, panY: 175, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` }); } - @action.bound openSearch(e: React.PointerEvent) { + @action.bound + openSearch(e: React.PointerEvent) { e.stopPropagation(); this._openNoResults = false; FilterBox.Instance.closeFilter(); @@ -326,12 +204,14 @@ import * as $ from 'jquery'; FilterBox.Instance._pointerTime = e.timeStamp; } - @action.bound closeSearch = () => { + @action.bound + closeSearch = () => { FilterBox.Instance.closeFilter(); this.closeResults(); } - @action.bound closeResults() { + @action.bound + closeResults() { this._resultsOpen = false; this._results = []; this._visibleElements = []; @@ -368,144 +248,73 @@ import * as $ from 'jquery'; this._isSearch = Array(this._numTotalResults === -1 ? 0 : this._numTotalResults); } - for (let i = 0; - i < this._numTotalResults; - - i++) { - + 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] =
    ; + this._visibleElements[i] =
    ; } } - else { if (this._isSearch[i] !== "search") { let result: Doc | undefined = undefined; - if (i >= this._results.length) { this.getResults(this._searchString); if (i < this._results.length) result = this._results[i]; - if (result) { - this._visibleElements[i] = ; + this._visibleElements[i] = ; this._isSearch[i] = "search"; } } - else { result = this._results[i]; - if (result) { - this._visibleElements[i] = ; + 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() { + @computed + get resFull() { + console.log(this._numTotalResults) return this._numTotalResults <= 8; } - @computed get resultHeight() { + @computed + get resultHeight() { return this._numTotalResults * 70; } render() { - return (
    { - this._visibleElements - } - -
    ); + return ( +
    +
    + + + + + +
    +
    + {this._visibleElements} +
    +
    + ); } } \ No newline at end of file diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx index cd7e31b20..134c13dc8 100644 --- a/src/client/views/search/SearchItem.tsx +++ b/src/client/views/search/SearchItem.tsx @@ -240,7 +240,7 @@ export class SearchItem extends React.Component {
    -
    +
    {StrCast(this.props.doc.title)}
    diff --git a/src/server/Search.ts b/src/server/Search.ts index ffba4ea8e..98f421937 100644 --- a/src/server/Search.ts +++ b/src/server/Search.ts @@ -18,6 +18,18 @@ export class Search { } } + public async updateDocuments(documents: any[]) { + try { + const res = await rp.post(this.url + "dash/update", { + headers: { 'content-type': 'application/json' }, + body: JSON.stringify(documents) + }); + return res; + } catch (e) { + // console.warn("Search error: " + e + document); + } + } + public async search(query: string, start: number = 0, rows: number = 10) { try { const searchResults = JSON.parse(await rp.get(this.url + "dash/select", { -- cgit v1.2.3-70-g09d2 From 29840e571c2f17d0bb346186dd91f1d895684a95 Mon Sep 17 00:00:00 2001 From: monikahedman Date: Sun, 14 Jul 2019 18:15:39 -0400 Subject: fixed no search results --- src/client/views/search/SearchBox.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index f5748d494..bfad9a845 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -230,7 +230,7 @@ export class SearchBox extends React.Component { this._startIndex = startIndex === -1 ? 0 : startIndex; this._endIndex = endIndex === -1 ? 12 : endIndex; - if (this._numTotalResults === 0 && this._openNoResults) { + if ((this._numTotalResults === 0 || this._results.length === 0) && this._openNoResults) { this._visibleElements = [
    No Search Results
    ]; return; } -- cgit v1.2.3-70-g09d2 From 606a494b4f0e259ce8d70b9ac4c5ab7b2bd0cd25 Mon Sep 17 00:00:00 2001 From: monikahedman Date: Sun, 14 Jul 2019 18:32:09 -0400 Subject: should be ready --- src/client/views/search/SearchItem.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx index 134c13dc8..9a9351429 100644 --- a/src/client/views/search/SearchItem.tsx +++ b/src/client/views/search/SearchItem.tsx @@ -99,7 +99,9 @@ export class SearchItem extends React.Component { @observable _selected: boolean = false; onClick = () => { - DocumentManager.Instance.jumpToDocument(this.props.doc, false); + // I dont think this is the best functionality because clicking the name of the collection does that. Change it back if you'd like + // DocumentManager.Instance.jumpToDocument(this.props.doc, false); + CollectionDockingView.Instance.AddRightSplit(this.props.doc, undefined); } @observable _useIcons = true; @observable _displayDim = 50; -- cgit v1.2.3-70-g09d2 From 8c80710f241376043e8700ec79277fc039f3a00b Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sun, 14 Jul 2019 22:19:33 -0400 Subject: Cleaned up imports --- src/client/views/search/SearchBox.tsx | 9 --------- 1 file changed, 9 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index bfad9a845..67aaa387c 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -15,10 +15,6 @@ import { Id } from '../../../new_fields/FieldSymbols'; import { SearchUtil } from '../../util/SearchUtil'; import { RouteStore } from '../../../server/RouteStore'; import { FilterBox } from './FilterBox'; -import { start } from 'repl'; -import { getForkTsCheckerWebpackPluginHooks } from 'fork-ts-checker-webpack-plugin/lib/hooks'; -import { faThumbsDown } from '@fortawesome/free-regular-svg-icons'; -import * as $ from 'jquery'; @observer @@ -32,7 +28,6 @@ export class SearchBox extends React.Component { private _isSearch: ("search" | "placeholder" | undefined)[] = []; private _numTotalResults = -1; - private _startIndex = -1; private _endIndex = -1; static Instance: SearchBox; @@ -65,7 +60,6 @@ export class SearchBox extends React.Component { this._results = []; this._visibleElements = []; this._numTotalResults = -1; - this._startIndex = -1; this._endIndex = -1; this._curRequest = undefined; this._maxSearchIndex = 0; @@ -103,7 +97,6 @@ export class SearchBox extends React.Component { return; } else { - this._startIndex = 0; this._endIndex = 12; this._maxSearchIndex = 0; this._numTotalResults = -1; @@ -216,7 +209,6 @@ export class SearchBox extends React.Component { this._results = []; this._visibleElements = []; this._numTotalResults = -1; - this._startIndex = -1; this._endIndex = -1; this._curRequest = undefined; } @@ -227,7 +219,6 @@ export class SearchBox extends React.Component { let startIndex = Math.floor(Math.max(0, scrollY / 70 - buffer)); let endIndex = Math.ceil(Math.min(this._numTotalResults - 1, startIndex + (560 / 70) + buffer)); - this._startIndex = startIndex === -1 ? 0 : startIndex; this._endIndex = endIndex === -1 ? 12 : endIndex; if ((this._numTotalResults === 0 || this._results.length === 0) && this._openNoResults) { -- cgit v1.2.3-70-g09d2 From 0f429c53fc3df62a60be1da398740524545357bc Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sun, 14 Jul 2019 22:27:59 -0400 Subject: Compile errors --- src/client/views/pdf/PDFMenu.tsx | 4 +- src/client/views/pdf/Page.tsx | 2 +- src/client/views/search/Pager.scss | 47 --------------------- src/client/views/search/Pager.tsx | 78 ----------------------------------- src/client/views/search/SearchBox.tsx | 5 ++- 5 files changed, 6 insertions(+), 130 deletions(-) delete mode 100644 src/client/views/search/Pager.scss delete mode 100644 src/client/views/search/Pager.tsx (limited to 'src/client/views/search') diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx index e73b759df..27c2a8f1a 100644 --- a/src/client/views/pdf/PDFMenu.tsx +++ b/src/client/views/pdf/PDFMenu.tsx @@ -18,7 +18,7 @@ export default class PDFMenu extends React.Component { @observable private _transitionDelay: string = ""; - StartDrag: (e: PointerEvent, ele: HTMLDivElement) => void = emptyFunction; + StartDrag: (e: PointerEvent, ele: HTMLElement) => void = emptyFunction; Highlight: (d: Doc | undefined, color: string | undefined) => void = emptyFunction; Delete: () => void = emptyFunction; Snippet: (marquee: { left: number, top: number, width: number, height: number }) => void = emptyFunction; @@ -34,7 +34,7 @@ export default class PDFMenu extends React.Component { private _offsetY: number = 0; private _offsetX: number = 0; private _mainCont: React.RefObject = React.createRef(); - private _commentCont: React.RefObject = React.createRef(); + private _commentCont = React.createRef(); private _snippetButton: React.RefObject = React.createRef(); private _dragging: boolean = false; @observable private _keyValue: string = ""; diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx index 1e22aca9e..b4a4b5806 100644 --- a/src/client/views/pdf/Page.tsx +++ b/src/client/views/pdf/Page.tsx @@ -152,7 +152,7 @@ export default class Page extends React.Component { * start a drag event and create or put the necessary info into the drag event. */ @action - startDrag = (e: PointerEvent, ele: HTMLDivElement): void => { + startDrag = (e: PointerEvent, ele: HTMLElement): void => { e.preventDefault(); e.stopPropagation(); let thisDoc = this.props.parent.Document; diff --git a/src/client/views/search/Pager.scss b/src/client/views/search/Pager.scss deleted file mode 100644 index 2b9c81b93..000000000 --- a/src/client/views/search/Pager.scss +++ /dev/null @@ -1,47 +0,0 @@ -@import "../globalCssVariables"; - -.search-pager { - background-color: $dark-color; - border-radius: 10px; - width: 500px; - display: flex; - justify-content: center; - // margin-left: 27px; - float: right; - margin-right: 74px; - margin-left: auto; - - // flex-direction: column; - - .search-arrows { - display: flex; - justify-content: center; - margin: 10px; - width: 50%; - - .arrow { - -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; - - .fontawesome-icon { - color: $light-color; - width: 20px; - height: 20px; - margin-right: 2px; - margin-left: 2px; - // opacity: .7; - } - } - - .pager-title { - text-align: center; - // font-size: 8px; - // margin-bottom: 10px; - color: $light-color; - // padding: 2px; - width: 40%; - } - } -} \ No newline at end of file diff --git a/src/client/views/search/Pager.tsx b/src/client/views/search/Pager.tsx deleted file mode 100644 index 1c62773b1..000000000 --- a/src/client/views/search/Pager.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { faArrowCircleRight, faArrowCircleLeft } from '@fortawesome/free-solid-svg-icons'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { library } from '@fortawesome/fontawesome-svg-core'; -import "./Pager.scss"; -import { SearchBox } from './SearchBox'; -import { observable, action } from 'mobx'; -import { FilterBox } from './FilterBox'; - -library.add(faArrowCircleRight); -library.add(faArrowCircleLeft); - -@observer -export class Pager extends React.Component { - - @observable _leftHover: boolean = false; - @observable _rightHover: boolean = false; - - @action - onLeftClick(e: React.PointerEvent) { - FilterBox.Instance._pointerTime = e.timeStamp; - if (SearchBox.Instance._pageNum > 0) { - SearchBox.Instance._pageNum -= 1; - } - } - - @action - onRightClick(e: React.PointerEvent) { - FilterBox.Instance._pointerTime = e.timeStamp; - if (SearchBox.Instance._pageNum + 1 < SearchBox.Instance._maxNum) { - SearchBox.Instance._pageNum += 1; - } - } - - @action.bound - mouseInLeft() { - this._leftHover = true; - } - - @action.bound - mouseOutLeft() { - this._leftHover = false; - } - - @action.bound - mouseInRight() { - this._rightHover = true; - } - - @action.bound - mouseOutRight() { - this._rightHover = false; - } - - render() { - return ( -
    -
    -
    - -
    -
    - page {SearchBox.Instance._pageNum + 1} of {SearchBox.Instance._maxNum} -
    -
    - -
    -
    -
    - ); - } - -} \ No newline at end of file diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index c02db528a..e0c5d163e 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -213,7 +213,8 @@ export class SearchBox extends React.Component { this._curRequest = undefined; } - resultsScrolled = flow(function* (this: SearchBox, e?: React.UIEvent) { + @action + resultsScrolled = (e?: React.UIEvent) => { let scrollY = e ? e.currentTarget.scrollTop : 0; let buffer = 4; let startIndex = Math.floor(Math.max(0, scrollY / 70 - buffer)); @@ -273,7 +274,7 @@ export class SearchBox extends React.Component { this._visibleElements.length = this._results.length; this._isSearch.length = this._results.length; } - }); + } @computed get resFull() { -- cgit v1.2.3-70-g09d2 From 756b6590723c307440d7c69f9ad91073ad0f7a24 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sun, 14 Jul 2019 23:33:35 -0400 Subject: Some search fixes and tweaks --- src/client/util/SerializationHelper.ts | 7 +- src/client/views/search/SearchBox.tsx | 55 +++--- src/client/views/search/SearchItem.scss | 303 ++++++++++++++++---------------- 3 files changed, 187 insertions(+), 178 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/util/SerializationHelper.ts b/src/client/util/SerializationHelper.ts index 17ae407c4..429fb22d9 100644 --- a/src/client/util/SerializationHelper.ts +++ b/src/client/util/SerializationHelper.ts @@ -1,5 +1,6 @@ import { PropSchema, serialize, deserialize, custom, setDefaultModelSchema, getDefaultModelSchema, primitive, SKIP } from "serializr"; import { Field } from "../../new_fields/Doc"; +import { ClientUtils } from "./ClientUtils"; export namespace SerializationHelper { let serializing: number = 0; @@ -38,7 +39,11 @@ export namespace SerializationHelper { serializing += 1; if (!obj.__type) { - throw Error("No property 'type' found in JSON."); + if (ClientUtils.RELEASE) { + return undefined; + } else { + throw Error("No property 'type' found in JSON."); + } } if (!(obj.__type in serializationTypes)) { diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index e0c5d163e..dc1d35b1c 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -26,6 +26,8 @@ export class SearchBox extends React.Component { @observable private _openNoResults: boolean = false; @observable private _visibleElements: JSX.Element[] = []; + private resultsRef = React.createRef(); + private _isSearch: ("search" | "placeholder" | undefined)[] = []; private _numTotalResults = -1; private _endIndex = -1; @@ -114,37 +116,34 @@ export class SearchBox extends React.Component { return SearchUtil.Search(query, true, 0, 10000000); } - getResults = async (query: string) => { - - while (this._results.length <= this._endIndex && (this._numTotalResults === -1 || this._maxSearchIndex < this._numTotalResults)) { - let prom: Promise; - if (this._curRequest) { - prom = this._curRequest; - return; - } else { - prom = SearchUtil.Search(query, true, this._maxSearchIndex, 10); - this._maxSearchIndex += 10; - } - prom.then(action((res: SearchUtil.DocSearchResult) => { + 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, this._maxSearchIndex, 10).then(action((res: SearchUtil.DocSearchResult) => { - // happens at the beginning - if (res.numFound !== this._numTotalResults && this._numTotalResults === -1) { - this._numTotalResults = res.numFound; - } + // happens at the beginning + if (res.numFound !== this._numTotalResults && this._numTotalResults === -1) { + this._numTotalResults = res.numFound; + } - let filteredDocs = FilterBox.Instance.filterDocsByType(res.docs); - this._results.push(...filteredDocs); + let filteredDocs = FilterBox.Instance.filterDocsByType(res.docs); + this._results.push(...filteredDocs); - if (prom === this._curRequest) { this._curRequest = undefined; - } - })); - - this._curRequest = prom; + })); + this._maxSearchIndex += 10; - await prom; - } + await this._curRequest; + } + this.resultsScrolled(); + res(); + }); + return this.lockPromise; } collectionRef = React.createRef(); @@ -215,7 +214,7 @@ export class SearchBox extends React.Component { @action resultsScrolled = (e?: React.UIEvent) => { - let scrollY = e ? e.currentTarget.scrollTop : 0; + let scrollY = e ? e.currentTarget.scrollTop : this.resultsRef.current ? this.resultsRef.current.scrollTop : 0; let buffer = 4; let startIndex = Math.floor(Math.max(0, scrollY / 70 - buffer)); let endIndex = Math.ceil(Math.min(this._numTotalResults - 1, startIndex + (560 / 70) + buffer)); @@ -246,7 +245,7 @@ export class SearchBox extends React.Component { if (i < startIndex || i > endIndex) { if (this._isSearch[i] !== "placeholder") { this._isSearch[i] = "placeholder"; - this._visibleElements[i] =
    ; + this._visibleElements[i] =
    Loading...
    ; } } else { @@ -303,7 +302,7 @@ export class SearchBox extends React.Component {
    + }} ref={this.resultsRef}> {this._visibleElements}
    diff --git a/src/client/views/search/SearchItem.scss b/src/client/views/search/SearchItem.scss index 0fb93daad..24dd2eaa3 100644 --- a/src/client/views/search/SearchItem.scss +++ b/src/client/views/search/SearchItem.scss @@ -6,195 +6,200 @@ justify-content: flex-end; height: 70px; z-index: 0; +} - .search-item { - width: 500px; - background: $light-color-secondary; - border-color: $intermediate-color; - border-bottom-style: solid; - padding: 10px; - height: 70px; - z-index: 0; - display: inline-block; - - .main-search-info { - display: flex; - flex-direction: row; - width: 100%; +.searchBox-placeholder, +.search-overview .search-item { + width: 500px; + background: $light-color-secondary; + border-color: $intermediate-color; + border-bottom-style: solid; + padding: 10px; + height: 70px; + z-index: 0; + display: inline-block; - .search-title { - text-transform: uppercase; - text-align: left; - width: 100%; - font-weight: bold; - } + .main-search-info { + display: flex; + flex-direction: row; + width: 100%; - .search-info { + .search-title { + text-transform: uppercase; + text-align: left; + width: 100%; + font-weight: bold; + } + + .search-info { + display: flex; + justify-content: flex-end; + + .link-container.item { + margin-left: auto; + margin-right: auto; + height: 26px; + width: 26px; + border-radius: 13px; + background: $dark-color; + color: $light-color-secondary; display: flex; - justify-content: flex-end; - - .link-container.item { - margin-left: auto; - margin-right: auto; - height: 26px; - width: 26px; - border-radius: 13px; - background: $dark-color; - color: $light-color-secondary; - display: flex; - justify-content: center; - align-items: center; - -webkit-transition: all 0.2s ease-in-out; - -moz-transition: all 0.2s ease-in-out; - -o-transition: all 0.2s ease-in-out; - transition: all 0.2s ease-in-out; - transform-origin: top right; - overflow: hidden; + justify-content: center; + align-items: center; + -webkit-transition: all 0.2s ease-in-out; + -moz-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + transform-origin: top right; + overflow: hidden; + position: relative; + + .link-count { + opacity: 1; + position: absolute; + z-index: 1000; + text-align: center; + -webkit-transition: opacity 0.2s ease-in-out; + -moz-transition: opacity 0.2s ease-in-out; + -o-transition: opacity 0.2s ease-in-out; + transition: opacity 0.2s ease-in-out; + } + + .link-extended { + // display: none; + visibility: hidden; + opacity: 0; position: relative; + z-index: 500; + overflow: hidden; + -webkit-transition: opacity 0.2s ease-in-out .2s, visibility 0s linear 0s; + -moz-transition: opacity 0.2s ease-in-out .2s, visibility 0s linear 0s; + -o-transition: opacity 0.2s ease-in-out .2s, visibility 0s linear 0s; + transition: opacity 0.2s ease-in-out .2s, visibility 0s linear 0s; + // transition-delay: 1s; + } - .link-count { - opacity: 1; - position: absolute; - z-index: 1000; - text-align: center; - -webkit-transition: opacity 0.2s ease-in-out; - -moz-transition: opacity 0.2s ease-in-out; - -o-transition: opacity 0.2s ease-in-out; - transition: opacity 0.2s ease-in-out; - } + } - .link-extended { - // display: none; - visibility: hidden; - opacity: 0; - position: relative; - z-index: 500; - overflow: hidden; - -webkit-transition: opacity 0.2s ease-in-out .2s, visibility 0s linear 0s; - -moz-transition: opacity 0.2s ease-in-out .2s, visibility 0s linear 0s; - -o-transition: opacity 0.2s ease-in-out .2s, visibility 0s linear 0s; - transition: opacity 0.2s ease-in-out .2s, visibility 0s linear 0s; - // transition-delay: 1s; - } + .link-container.item:hover { + width: 70px; + } - } + .link-container.item:hover .link-count { + opacity: 0; + } - .link-container.item:hover { - width: 70px; - } + .link-container.item:hover .link-extended { + opacity: 1; + visibility: visible; + // display: inline; + } - .link-container.item:hover .link-count { - opacity: 0; - } + .icon-icons { + width: 50px + } - .link-container.item:hover .link-extended { - opacity: 1; - visibility: visible; - // display: inline; - } + .icon-live { + width: 175px; + } - .icon-icons { - width: 50px - } + .icon-icons, + .icon-live { + height: 50px; + margin: auto; + overflow: hidden; - .icon-live { - width: 175px; + .search-type { + display: inline-block; + width: 100%; + position: absolute; + justify-content: center; + align-items: center; + position: relative; + margin-right: 5px; } - .icon-icons, - .icon-live { - height: 50px; - margin: auto; + .pdfBox-cont { overflow: hidden; - .search-type { - display: inline-block; - width: 100%; - position: absolute; - justify-content: center; - align-items: center; - position: relative; - margin-right: 5px; - } - - .pdfBox-cont { - overflow: hidden; - - img { - width: 100% !important; - height: auto !important; - } + img { + width: 100% !important; + height: auto !important; } + } - .search-type:hover+.search-label { - opacity: 1; - } + .search-type:hover+.search-label { + opacity: 1; + } - .search-label { - font-size: 10; - position: relative; - right: 0px; - text-transform: capitalize; - opacity: 0; - -webkit-transition: opacity 0.2s ease-in-out; - -moz-transition: opacity 0.2s ease-in-out; - -o-transition: opacity 0.2s ease-in-out; - transition: opacity 0.2s ease-in-out; - } + .search-label { + font-size: 10; + position: relative; + right: 0px; + text-transform: capitalize; + opacity: 0; + -webkit-transition: opacity 0.2s ease-in-out; + -moz-transition: opacity 0.2s ease-in-out; + -o-transition: opacity 0.2s ease-in-out; + transition: opacity 0.2s ease-in-out; } + } - .icon-live:hover { - height: 175px; + .icon-live:hover { + height: 175px; - .pdfBox-cont { - img { - width: 100% !important; - } + .pdfBox-cont { + img { + width: 100% !important; } } } - - .search-info:hover { - width: 60%; - } } - } - .search-item:hover~.searchBox-instances, - .searchBox-instances:hover, - .searchBox-instances:active { - opacity: 1; - background: $lighter-alt-accent; - -webkit-transform: scale(1); - -ms-transform: scale(1); - transform: scale(1); + .search-info:hover { + width: 60%; + } } +} - .search-item:hover { - transition: all 0.2s; - background: $lighter-alt-accent; - } +.search-item:hover~.searchBox-instances, +.searchBox-instances:hover, +.searchBox-instances:active { + opacity: 1; + background: $lighter-alt-accent; + -webkit-transform: scale(1); + -ms-transform: scale(1); + transform: scale(1); +} - .searchBox-instances { - float: left; - opacity: 1; - width: 150px; - transition: all 0.2s ease; - color: black; - transform-origin: top right; - -webkit-transform: scale(0); - -ms-transform: scale(0); - transform: scale(0); - } +.search-item:hover { + transition: all 0.2s; + background: $lighter-alt-accent; +} +.searchBox-instances { + float: left; + opacity: 1; + width: 150px; + transition: all 0.2s ease; + color: black; + transform-origin: top right; + -webkit-transform: scale(0); + -ms-transform: scale(0); + transform: scale(0); } + .search-overview:hover { z-index: 1; } .searchBox-placeholder { min-height: 70px; + margin-left: 150px; + text-transform: uppercase; + text-align: left; + font-weight: bold; } .collection { -- cgit v1.2.3-70-g09d2 From b72dfe96af4f87fa00e9d64ffded62d0a5ec0ea9 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 15 Jul 2019 17:20:40 -0400 Subject: Added filter query to search to better support type filtering --- src/client/util/SearchUtil.ts | 22 +++++++++++----------- .../views/collections/ParentDocumentSelector.tsx | 4 ++-- src/client/views/globalCssVariables.scss | 13 ++++++++----- src/client/views/search/FilterBox.tsx | 4 ++++ src/client/views/search/SearchBox.tsx | 11 ++++++++--- src/client/views/search/SearchItem.tsx | 4 ++-- src/server/Search.ts | 3 ++- src/server/index.ts | 4 ++-- 8 files changed, 39 insertions(+), 26 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts index 674eeb1a8..a3858da9f 100644 --- a/src/client/util/SearchUtil.ts +++ b/src/client/util/SearchUtil.ts @@ -14,11 +14,11 @@ export namespace SearchUtil { numFound: number; } - export function Search(query: string, returnDocs: true, start?: number, count?: number): Promise; - export function Search(query: string, returnDocs: false, start?: number, count?: number): Promise; - export async function Search(query: string, returnDocs: boolean, start?: number, rows?: number) { + export function Search(query: string, filterQuery: string | undefined, returnDocs: true, start?: number, count?: number): Promise; + export function Search(query: string, filterQuery: string | undefined, returnDocs: false, start?: number, count?: number): Promise; + export async function Search(query: string, filterQuery: string | undefined, returnDocs: boolean, start?: number, rows?: number) { const result: IdSearchResult = JSON.parse(await rp.get(DocServer.prepend("/search"), { - qs: { query, start, rows } + qs: { query, filterQuery, start, rows }, })); if (!returnDocs) { return result; @@ -35,31 +35,31 @@ export namespace SearchUtil { const proto = Doc.GetProto(doc); const protoId = proto[Id]; if (returnDocs) { - return (await Search(`proto_i:"${protoId}"`, returnDocs)).docs; + return (await Search("", `proto_i:"${protoId}"`, returnDocs)).docs; } else { - return (await Search(`proto_i:"${protoId}"`, returnDocs)).ids; + return (await Search("", `proto_i:"${protoId}"`, returnDocs)).ids; } // return Search(`{!join from=id to=proto_i}id:${protoId}`, true); } export async function GetViewsOfDocument(doc: Doc): Promise { - const results = await Search(`proto_i:"${doc[Id]}"`, true); + const results = await Search("", `proto_i:"${doc[Id]}"`, true); return results.docs; } export async function GetContextsOfDocument(doc: Doc): Promise<{ contexts: Doc[], aliasContexts: Doc[] }> { - const docContexts = (await Search(`data_l:"${doc[Id]}"`, true)).docs; + const docContexts = (await Search("", `data_l:"${doc[Id]}"`, true)).docs; const aliases = await GetAliasesOfDocument(doc, false); - const aliasContexts = (await Promise.all(aliases.map(doc => Search(`data_l:"${doc}"`, true)))); + const aliasContexts = (await Promise.all(aliases.map(doc => Search("", `data_l:"${doc}"`, true)))); const contexts = { contexts: docContexts, aliasContexts: [] as Doc[] }; aliasContexts.forEach(result => contexts.aliasContexts.push(...result.docs)); return contexts; } export async function GetContextIdsOfDocument(doc: Doc): Promise<{ contexts: string[], aliasContexts: string[] }> { - const docContexts = (await Search(`data_l:"${doc[Id]}"`, false)).ids; + const docContexts = (await Search("", `data_l:"${doc[Id]}"`, false)).ids; const aliases = await GetAliasesOfDocument(doc, false); - const aliasContexts = (await Promise.all(aliases.map(doc => Search(`data_l:"${doc}"`, false)))); + const aliasContexts = (await Promise.all(aliases.map(doc => Search("", `data_l:"${doc}"`, false)))); const contexts = { contexts: docContexts, aliasContexts: [] as string[] }; aliasContexts.forEach(result => contexts.aliasContexts.push(...result.ids)); return contexts; diff --git a/src/client/views/collections/ParentDocumentSelector.tsx b/src/client/views/collections/ParentDocumentSelector.tsx index c0f489cd8..a97aa4f36 100644 --- a/src/client/views/collections/ParentDocumentSelector.tsx +++ b/src/client/views/collections/ParentDocumentSelector.tsx @@ -23,9 +23,9 @@ export class SelectorContextMenu extends React.Component { async fetchDocuments() { let aliases = (await SearchUtil.GetAliasesOfDocument(this.props.Document)).filter(doc => doc !== this.props.Document); - const { docs } = await SearchUtil.Search(`data_l:"${this.props.Document[Id]}"`, true); + const { docs } = await SearchUtil.Search("", `data_l:"${this.props.Document[Id]}"`, true); const map: Map = new Map; - const allDocs = await Promise.all(aliases.map(doc => SearchUtil.Search(`data_l:"${doc[Id]}"`, true).then(result => result.docs))); + const allDocs = await Promise.all(aliases.map(doc => SearchUtil.Search("", `data_l:"${doc[Id]}"`, true).then(result => result.docs))); allDocs.forEach((docs, index) => docs.forEach(doc => map.set(doc, aliases[index]))); docs.forEach(doc => map.delete(doc)); runInAction(() => { diff --git a/src/client/views/globalCssVariables.scss b/src/client/views/globalCssVariables.scss index fec105516..6dffee586 100644 --- a/src/client/views/globalCssVariables.scss +++ b/src/client/views/globalCssVariables.scss @@ -13,23 +13,26 @@ $darker-alt-accent: rgb(178, 206, 248); $intermediate-color: #9c9396; $dark-color: #121721; // fonts -$sans-serif: "Noto Sans", sans-serif; +$sans-serif: "Noto Sans", +sans-serif; // $sans-serif: "Roboto Slab", sans-serif; -$serif: "Crimson Text", serif; +$serif: "Crimson Text", +serif; // misc values $border-radius: 0.3em; // $search-thumnail-size: 175; - // dragged items -$contextMenu-zindex: 1000; // context menu shows up over everything +// dragged items +$contextMenu-zindex: 100000; // context menu shows up over everything $mainTextInput-zindex: 999; // then text input overlay so that it's context menu will appear over decorations, etc $docDecorations-zindex: 998; // then doc decorations appear over everything else $remoteCursors-zindex: 997; // ... not sure what level the remote cursors should go -- is this right? $COLLECTION_BORDER_WIDTH: 1; $MINIMIZED_ICON_SIZE:25; $MAX_ROW_HEIGHT: 44px; -:export { + +:export { contextMenuZindex: $contextMenu-zindex; COLLECTION_BORDER_WIDTH: $COLLECTION_BORDER_WIDTH; MINIMIZED_ICON_SIZE: $MINIMIZED_ICON_SIZE; diff --git a/src/client/views/search/FilterBox.tsx b/src/client/views/search/FilterBox.tsx index 435ca86e3..f11fb008c 100644 --- a/src/client/views/search/FilterBox.tsx +++ b/src/client/views/search/FilterBox.tsx @@ -237,6 +237,10 @@ export class FilterBox extends React.Component { return "+(" + finalColString + ")" + query; } + get filterTypes() { + return this._icons.length === 9 ? undefined : this._icons; + } + @action filterDocsByType(docs: Doc[]) { if (this._icons.length === 9) { diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index dc1d35b1c..1b4427e66 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -67,7 +67,7 @@ export class SearchBox extends React.Component { this._maxSearchIndex = 0; } - enter = (e: React.KeyboardEvent) => { if (e.key === "Enter") { this.submitSearch(); } } + enter = (e: React.KeyboardEvent) => { if (e.key === "Enter") { this.submitSearch(); } }; public static async convertDataUri(imageUri: string, returnedFilename: string) { try { @@ -113,7 +113,12 @@ export class SearchBox extends React.Component { } getAllResults = async (query: string) => { - return SearchUtil.Search(query, true, 0, 10000000); + return SearchUtil.Search(query, this.filterQuery, true, 0, 10000000); + } + + private get filterQuery() { + const types = FilterBox.Instance.filterTypes; + return types && types.map(type => `{!join from=id to=proto_i}type_t:"${type}"`).join(" "); } @@ -124,7 +129,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, this._maxSearchIndex, 10).then(action((res: SearchUtil.DocSearchResult) => { + this._curRequest = SearchUtil.Search(query, this.filterQuery, true, this._maxSearchIndex, 10).then(action((res: SearchUtil.DocSearchResult) => { // happens at the beginning if (res.numFound !== this._numTotalResults && this._numTotalResults === -1) { diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx index 16ad71d16..e34d101a8 100644 --- a/src/client/views/search/SearchItem.tsx +++ b/src/client/views/search/SearchItem.tsx @@ -51,9 +51,9 @@ export class SelectorContextMenu extends React.Component { async fetchDocuments() { let aliases = (await SearchUtil.GetViewsOfDocument(this.props.doc)).filter(doc => doc !== this.props.doc); - const { docs } = await SearchUtil.Search(`data_l:"${this.props.doc[Id]}"`, true); + const { docs } = await SearchUtil.Search("", `data_l:"${this.props.doc[Id]}"`, true); const map: Map = new Map; - const allDocs = await Promise.all(aliases.map(doc => SearchUtil.Search(`data_l:"${doc[Id]}"`, true).then(result => result.docs))); + const allDocs = await Promise.all(aliases.map(doc => SearchUtil.Search("", `data_l:"${doc[Id]}"`, true).then(result => result.docs))); allDocs.forEach((docs, index) => docs.forEach(doc => map.set(doc, aliases[index]))); docs.forEach(doc => map.delete(doc)); runInAction(() => { diff --git a/src/server/Search.ts b/src/server/Search.ts index 98f421937..fd9cec331 100644 --- a/src/server/Search.ts +++ b/src/server/Search.ts @@ -30,11 +30,12 @@ export class Search { } } - public async search(query: string, start: number = 0, rows: number = 10) { + public async search(query: string, filterQuery: string = "", start: number = 0, rows: number = 10) { try { const searchResults = JSON.parse(await rp.get(this.url + "dash/select", { qs: { q: query, + fq: filterQuery, fl: "id", start, rows, diff --git a/src/server/index.ts b/src/server/index.ts index 58af074aa..1c0dec05b 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -144,12 +144,12 @@ app.get("/pull", (req, res) => // GETTERS app.get("/search", async (req, res) => { - const { query, start, rows } = req.query; + const { query, filterQuery, start, rows } = req.query; if (query === undefined) { res.send([]); return; } - let results = await Search.Instance.search(query, start, rows); + let results = await Search.Instance.search(query, filterQuery, start, rows); res.send(results); }); -- cgit v1.2.3-70-g09d2 From ce8684aae01fb8329b9523737839ee814afeb4a4 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 15 Jul 2019 17:38:52 -0400 Subject: Search tweak --- src/client/views/search/SearchBox.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 1b4427e66..1f461a4a7 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -118,7 +118,7 @@ export class SearchBox extends React.Component { private get filterQuery() { const types = FilterBox.Instance.filterTypes; - return types && types.map(type => `{!join from=id to=proto_i}type_t:"${type}"`).join(" "); + return types && types.map(type => `({!join from=id to=proto_i}type_t:"${type} AND NOT type_t:*) OR type_t:"${type}"`).join(" "); } -- cgit v1.2.3-70-g09d2 From 9ab19fd503764f40d27769c90b4936ddd39eb750 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 15 Jul 2019 17:41:15 -0400 Subject: from last --- src/client/views/search/SearchBox.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 1f461a4a7..7bfe0bb13 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -118,7 +118,7 @@ export class SearchBox extends React.Component { private get filterQuery() { const types = FilterBox.Instance.filterTypes; - return types && types.map(type => `({!join from=id to=proto_i}type_t:"${type} AND NOT type_t:*) OR type_t:"${type}"`).join(" "); + return types && types.map(type => `({!join from=id to=proto_i}type_t:"${type}" AND NOT type_t:*) OR type_t:"${type}"`).join(" "); } -- cgit v1.2.3-70-g09d2 From 4c127ddd32b20bc6f1e6fb6b921e06cf3de4f1ca Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 15 Jul 2019 18:57:02 -0400 Subject: added proto filter to search --- src/client/views/search/SearchBox.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 7bfe0bb13..3830a6d16 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -118,7 +118,7 @@ export class SearchBox extends React.Component { private get filterQuery() { const types = FilterBox.Instance.filterTypes; - return types && types.map(type => `({!join from=id to=proto_i}type_t:"${type}" AND NOT type_t:*) OR type_t:"${type}"`).join(" "); + return "proto_i:*" + (types ? ` AND (${types.map(type => `({!join from=id to=proto_i}type_t:"${type}" AND NOT type_t:*) OR type_t:"${type}"`).join(" ")})` : ""); } -- cgit v1.2.3-70-g09d2 From 533c48010ca668a944962bd61cd65115fc5a6fa6 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Tue, 16 Jul 2019 12:04:21 -0400 Subject: linter and error fixes --- src/client/documents/Documents.ts | 2 +- src/client/views/InkingControl.tsx | 4 ++-- src/client/views/Main.tsx | 2 +- src/client/views/collections/CollectionDockingView.tsx | 4 ++-- src/client/views/collections/CollectionTreeView.tsx | 2 +- src/client/views/nodes/ImageBox.tsx | 2 +- src/client/views/nodes/VideoBox.tsx | 4 ++-- src/client/views/nodes/WebBox.tsx | 2 +- src/client/views/search/SearchBox.tsx | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index ada9f3610..177810444 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -98,7 +98,7 @@ export namespace Docs { type LayoutSource = { LayoutString: () => string }; type CollectionLayoutSource = { LayoutString: (fieldStr: string, fieldExt?: string) => string }; - type CollectionViewType = [CollectionLayoutSource, string, string?] + type CollectionViewType = [CollectionLayoutSource, string, string?]; type PrototypeTemplate = { layout: { view: LayoutSource, diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx index c7f7bdb66..1910e409b 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -1,5 +1,5 @@ import { observable, action, computed, runInAction } from "mobx"; -import { ColorResult } from 'react-color'; +import { ColorState } from 'react-color'; import React = require("react"); import { observer } from "mobx-react"; import "./InkingControl.scss"; @@ -41,7 +41,7 @@ export class InkingControl extends React.Component { } @undoBatch - switchColor = action((color: ColorResult): void => { + switchColor = action((color: ColorState): void => { this._selectedColor = color.hex + (color.rgb.a !== undefined ? this.decimalToHexString(Math.round(color.rgb.a * 255)) : "ff"); if (InkingControl.Instance.selectedTool === InkTool.None) { if (MainOverlayTextBox.Instance.SetColor(color.hex)) return; diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 80399e24b..86578af3e 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -26,7 +26,7 @@ let swapDocs = async () => { } CurrentUserUtils.UserDocument.linkManagerDoc = undefined; } -} +}; (async () => { const info = await CurrentUserUtils.loadCurrentUser(); diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 1069ebbdb..a193ff677 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -301,7 +301,7 @@ export class CollectionDockingView extends React.Component { CollectionDockingView.Instance._ignoreStateChange = JSON.stringify(CollectionDockingView.Instance._goldenLayout.toConfig()); - this.stateChanged() + this.stateChanged(); }, 10); } } @@ -606,7 +606,7 @@ export class DockedFrameRenderer extends React.Component { addDocTab={this.addDocTab} ContainingCollectionView={undefined} zoomToScale={emptyFunction} - getScale={returnOne} /> + getScale={returnOne} />; } @computed get content() { diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 0196fecff..c212cc97c 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -153,7 +153,7 @@ class TreeView extends React.Component { let docList = Cast(this.resolvedDataDoc[this.fieldKey], listSpec(Doc)); let doc = Cast(this.resolvedDataDoc[this.fieldKey], Doc); let isDoc = doc instanceof Doc || docList; - let c + let c; return
    this._collapsed = !this._collapsed)} style={{ color: StrCast(this.props.document.color, "black"), opacity: 0.4 }}> {}
    ; diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 73ae8955d..1df955f1f 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -33,7 +33,7 @@ export const pageSchema = createSchema({ curPage: "number", }); -interface window { +interface Window { MediaRecorder: MediaRecorder; } diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 66844cdd6..e90efb31c 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -108,7 +108,7 @@ export class VideoBox extends DocComponent(VideoD this._youtubeReactionDisposer = reaction(() => [this.props.isSelected(), DocumentDecorations.Instance.Interacting, InkingControl.Instance.selectedTool], () => { let interactive = InkingControl.Instance.selectedTool === InkTool.None && this.props.isSelected() && !DocumentDecorations.Instance.Interacting; this._youtubePlayer.getIframe().style.pointerEvents = interactive ? "all" : "none"; - }, { fireImmediately: true }) + }, { fireImmediately: true }); // let iframe = $(document.getElementById(`${videoid}-player`)!); // iframe.on("load", function () { // iframe.contents().find("head") @@ -120,7 +120,7 @@ export class VideoBox extends DocComponent(VideoD @action onYoutubePlayerStateChange = (event: any) => { console.log("event.data = " + event.data); - this.Playing = event.data == YT.PlayerState.PLAYING; + this.Playing = event.data === YT.PlayerState.PLAYING; if (this._youtubeSeekTo && this.Playing) { this._youtubePlayer.pauseVideo(); this._youtubeSeekTo = false; diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 96b972a1c..f0a9ec6d8 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -19,7 +19,7 @@ export function onYouTubeIframeAPIReady() { }); } // must cast as any to set property on window -const _global = (window /* browser */ || global /* node */) as any +const _global = (window /* browser */ || global /* node */) as any; _global.onYouTubeIframeAPIReady = onYouTubeIframeAPIReady; function onPlayerReady(event: any) { diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 3830a6d16..ec778b346 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -282,7 +282,7 @@ export class SearchBox extends React.Component { @computed get resFull() { - console.log(this._numTotalResults) + console.log(this._numTotalResults); return this._numTotalResults <= 8; } -- cgit v1.2.3-70-g09d2 From 7f6666500f157c5884377d714137426cf05e7569 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 16 Jul 2019 13:40:20 -0400 Subject: Changed search to display extension documents as the extended documents --- src/client/documents/Documents.ts | 2 +- src/client/views/InkingControl.tsx | 4 ++-- src/client/views/collections/CollectionVideoView.tsx | 2 +- src/client/views/search/SearchBox.tsx | 13 ++++++++----- 4 files changed, 12 insertions(+), 9 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 177810444..5bbfe1c49 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -235,7 +235,7 @@ export namespace Docs { let title = prototypeId.toUpperCase().replace(upper, `_${upper}`); // synthesize the default options, the type and title from computed values and // whatever options pertain to this specific prototype - let options = { title: title, type: type, ...defaultOptions, ...(template.options || {}) }; + let options = { title: title, type: type, baseProto: true, ...defaultOptions, ...(template.options || {}) }; let primary = layout.view.LayoutString(); let collectionView = layout.collectionView; if (collectionView) { diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx index 1910e409b..c7f7bdb66 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -1,5 +1,5 @@ import { observable, action, computed, runInAction } from "mobx"; -import { ColorState } from 'react-color'; +import { ColorResult } from 'react-color'; import React = require("react"); import { observer } from "mobx-react"; import "./InkingControl.scss"; @@ -41,7 +41,7 @@ export class InkingControl extends React.Component { } @undoBatch - switchColor = action((color: ColorState): void => { + switchColor = action((color: ColorResult): void => { this._selectedColor = color.hex + (color.rgb.a !== undefined ? this.decimalToHexString(Math.round(color.rgb.a * 255)) : "ff"); if (InkingControl.Instance.selectedTool === InkTool.None) { if (MainOverlayTextBox.Instance.SetColor(color.hex)) return; diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx index faf507496..096e7e9d1 100644 --- a/src/client/views/collections/CollectionVideoView.tsx +++ b/src/client/views/collections/CollectionVideoView.tsx @@ -88,7 +88,7 @@ export class CollectionVideoView extends React.Component { canvas.width = 640; canvas.height = 640 * NumCast(this.props.Document.nativeHeight) / NumCast(this.props.Document.nativeWidth); var ctx = canvas.getContext('2d');//draw image to canvas. scale to target dimensions - this._videoBox!.player && ctx && ctx.drawImage(this._videoBox!.player!, 0, 0, canvas.width, canvas.height); + this._videoBox!.player && ctx && ctx.drawImage(this._videoBox!.player, 0, 0, canvas.width, canvas.height); //convert to desired file format var dataUrl = canvas.toDataURL('image/png'); // can also use 'image/png' diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index ec778b346..dc76d1ff4 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -6,7 +6,7 @@ import "./FilterBox.scss"; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { SetupDrag } from '../../util/DragManager'; import { Docs } from '../../documents/Documents'; -import { NumCast } from '../../../new_fields/Types'; +import { NumCast, Cast } from '../../../new_fields/Types'; import { Doc } from '../../../new_fields/Doc'; import { SearchItem } from './SearchItem'; import { DocServer } from '../../DocServer'; @@ -118,7 +118,7 @@ export class SearchBox extends React.Component { private get filterQuery() { const types = FilterBox.Instance.filterTypes; - return "proto_i:*" + (types ? ` AND (${types.map(type => `({!join from=id to=proto_i}type_t:"${type}" AND NOT type_t:*) OR type_t:"${type}"`).join(" ")})` : ""); + return "NOT baseProto_b:true" + (types ? ` AND (${types.map(type => `({!join from=id to=proto_i}type_t:"${type}" AND NOT type_t:*) OR type_t:"${type}"`).join(" ")})` : ""); } @@ -129,15 +129,18 @@ 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, this.filterQuery, true, this._maxSearchIndex, 10).then(action((res: SearchUtil.DocSearchResult) => { + this._curRequest = SearchUtil.Search(query, this.filterQuery, true, this._maxSearchIndex, 10).then(action(async (res: SearchUtil.DocSearchResult) => { // happens at the beginning if (res.numFound !== this._numTotalResults && this._numTotalResults === -1) { this._numTotalResults = res.numFound; } - let filteredDocs = FilterBox.Instance.filterDocsByType(res.docs); - this._results.push(...filteredDocs); + const docs = await Promise.all(res.docs.map(doc => Cast(doc.extendsDoc, Doc, doc as any))); + let filteredDocs = FilterBox.Instance.filterDocsByType(docs); + runInAction(() => { + this._results.push(...filteredDocs); + }); this._curRequest = undefined; })); -- cgit v1.2.3-70-g09d2 From 967638b84c15f35bbfb1c464ac8e22916a1a2bc7 Mon Sep 17 00:00:00 2001 From: monikahedman Date: Tue, 16 Jul 2019 14:31:20 -0400 Subject: changes --- src/client/views/search/FilterBox.tsx | 3 +++ src/client/views/search/SearchBox.scss | 4 ++-- src/client/views/search/SearchBox.tsx | 15 +++++++-------- 3 files changed, 12 insertions(+), 10 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/FilterBox.tsx b/src/client/views/search/FilterBox.tsx index f11fb008c..757665bcf 100644 --- a/src/client/views/search/FilterBox.tsx +++ b/src/client/views/search/FilterBox.tsx @@ -87,6 +87,9 @@ export class FilterBox extends React.Component { } }); + + let el = acc[i] as HTMLElement; + el.click(); } }); } diff --git a/src/client/views/search/SearchBox.scss b/src/client/views/search/SearchBox.scss index 324ba3063..109b88ac9 100644 --- a/src/client/views/search/SearchBox.scss +++ b/src/client/views/search/SearchBox.scss @@ -41,11 +41,10 @@ } .searchBox-results { - margin-right: 142px; + margin-right: 136px; top: 300px; display: flex; flex-direction: column; - margin-right: 72px; max-height: 560px; overflow: hidden; overflow-y: auto; @@ -60,5 +59,6 @@ text-transform: uppercase; text-align: left; font-weight: bold; + margin-left: 28px; } } \ No newline at end of file diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 3830a6d16..661c9c10b 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -22,6 +22,7 @@ export class SearchBox extends React.Component { @observable private _searchString: string = ""; @observable private _resultsOpen: boolean = false; + @observable private _searchbarOpen: boolean = false; @observable private _results: Doc[] = []; @observable private _openNoResults: boolean = false; @observable private _visibleElements: JSX.Element[] = []; @@ -107,6 +108,7 @@ export class SearchBox extends React.Component { runInAction(() => { this._resultsOpen = true; + this._searchbarOpen = true; this._openNoResults = true; this.resultsScrolled(); }); @@ -198,6 +200,7 @@ export class SearchBox extends React.Component { this._openNoResults = false; FilterBox.Instance.closeFilter(); this._resultsOpen = true; + this._searchbarOpen = true; FilterBox.Instance._pointerTime = e.timeStamp; } @@ -205,6 +208,7 @@ export class SearchBox extends React.Component { closeSearch = () => { FilterBox.Instance.closeFilter(); this.closeResults(); + this._searchbarOpen = false; } @action.bound @@ -281,15 +285,10 @@ export class SearchBox extends React.Component { } @computed - get resFull() { - console.log(this._numTotalResults) - return this._numTotalResults <= 8; - } + get resFull() { return this._numTotalResults <= 8; } @computed - get resultHeight() { - return this._numTotalResults * 70; - } + get resultHeight() { return this._numTotalResults * 70; } render() { return ( @@ -300,7 +299,7 @@ export class SearchBox extends React.Component { + style={{ width: this._searchbarOpen ? "500px" : "100px" }} />
    -- cgit v1.2.3-70-g09d2 From c6b933c6e89d5f438c434e8676cce9a6a577edbc Mon Sep 17 00:00:00 2001 From: monikahedman Date: Tue, 16 Jul 2019 14:35:35 -0400 Subject: checkbox --- src/client/views/search/FieldFilters.tsx | 2 +- src/client/views/search/FilterBox.tsx | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/FieldFilters.tsx b/src/client/views/search/FieldFilters.tsx index 648aac20a..7a33282d2 100644 --- a/src/client/views/search/FieldFilters.tsx +++ b/src/client/views/search/FieldFilters.tsx @@ -34,7 +34,7 @@ export class FieldFilters extends React.Component {
    - +
    ); } diff --git a/src/client/views/search/FilterBox.tsx b/src/client/views/search/FilterBox.tsx index 757665bcf..f28b074a7 100644 --- a/src/client/views/search/FilterBox.tsx +++ b/src/client/views/search/FilterBox.tsx @@ -40,7 +40,7 @@ export class FilterBox extends React.Component { @observable private _icons: string[] = this._allIcons; @observable private _titleFieldStatus: boolean = true; @observable private _authorFieldStatus: boolean = true; - @observable private _dataFieldStatus: boolean = true; + @observable public _deletedDocsStatus: boolean = false; @observable private _collectionStatus = false; @observable private _collectionSelfStatus = true; @observable private _collectionParentStatus = true; @@ -164,13 +164,13 @@ export class FilterBox extends React.Component { if (this._authorFieldStatus) { finalQuery = finalQuery + this.basicFieldFilters(query, Keys.AUTHOR); } - if (this._dataFieldStatus) { + if (this._deletedDocsStatus) { finalQuery = finalQuery + this.basicFieldFilters(query, Keys.DATA); } return finalQuery; } - get fieldFiltersApplied() { return !(this._dataFieldStatus && this._authorFieldStatus && this._titleFieldStatus); } + get fieldFiltersApplied() { return !(this._deletedDocsStatus && this._authorFieldStatus && this._titleFieldStatus); } //TODO: basically all of this //gets all of the collections of all the docviews that are selected @@ -308,7 +308,7 @@ export class FilterBox extends React.Component { updateAuthorStatus(newStat: boolean) { this._authorFieldStatus = newStat; } @action.bound - updateDataStatus(newStat: boolean) { this._dataFieldStatus = newStat; } + updateDataStatus(newStat: boolean) { this._deletedDocsStatus = newStat; } @action.bound updateCollectionStatus(newStat: boolean) { this._collectionStatus = newStat; } @@ -324,7 +324,7 @@ export class FilterBox extends React.Component { getParentCollectionStatus() { return this._collectionParentStatus; } getTitleStatus() { return this._titleFieldStatus; } getAuthorStatus() { return this._authorFieldStatus; } - getDataStatus() { return this._dataFieldStatus; } + getDataStatus() { return this._deletedDocsStatus; } // Useful queries: // Delegates of a document: {!join from=id to=proto_i}id:{protoId} @@ -376,7 +376,7 @@ export class FilterBox extends React.Component {
    -- cgit v1.2.3-70-g09d2 From 1b5bf295d951858a9d54e95e2ada4882f1a39f40 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 16 Jul 2019 14:41:18 -0400 Subject: Added start of deleted documents to search --- solr/conf/schema.xml | 1 + src/client/views/search/SearchBox.tsx | 3 +- src/server/GarbageCollector.ts | 87 +++++++++++++++++++++-------------- 3 files changed, 55 insertions(+), 36 deletions(-) (limited to 'src/client/views/search') diff --git a/solr/conf/schema.xml b/solr/conf/schema.xml index 8610786af..7a21794cb 100644 --- a/solr/conf/schema.xml +++ b/solr/conf/schema.xml @@ -44,6 +44,7 @@ + diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index dc76d1ff4..733e93a62 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -118,7 +118,8 @@ export class SearchBox extends React.Component { private get filterQuery() { const types = FilterBox.Instance.filterTypes; - return "NOT baseProto_b:true" + (types ? ` AND (${types.map(type => `({!join from=id to=proto_i}type_t:"${type}" AND NOT type_t:*) OR type_t:"${type}"`).join(" ")})` : ""); + const includeDeleted = false; + return "NOT baseProto_b:true" + (includeDeleted ? "" : " AND NOT deleted:true") + (types ? ` AND (${types.map(type => `({!join from=id to=proto_i}type_t:"${type}" AND NOT type_t:*) OR type_t:"${type}"`).join(" ")})` : ""); } diff --git a/src/server/GarbageCollector.ts b/src/server/GarbageCollector.ts index 59682e51e..ea5388004 100644 --- a/src/server/GarbageCollector.ts +++ b/src/server/GarbageCollector.ts @@ -59,7 +59,9 @@ function addDoc(doc: any, ids: string[], files: { [name: string]: string[] }) { } } -async function GarbageCollect() { +async function GarbageCollect(full: boolean = true) { + console.log("start GC"); + const start = Date.now(); // await new Promise(res => setTimeout(res, 3000)); const cursor = await Database.Instance.query({}, { userDocumentId: 1 }, 'users'); const users = await cursor.toArray(); @@ -68,7 +70,7 @@ async function GarbageCollect() { const files: { [name: string]: string[] } = {}; while (ids.length) { - const count = Math.min(ids.length, 100); + const count = Math.min(ids.length, 1000); const index = ids.length - count; const fetchIds = ids.splice(index, count).filter(id => !visited.has(id)); if (!fetchIds.length) { @@ -91,43 +93,58 @@ async function GarbageCollect() { cursor.close(); - const toDeleteCursor = await Database.Instance.query({ _id: { $nin: Array.from(visited) } }, { _id: 1 }); + const notToDelete = Array.from(visited); + const toDeleteCursor = await Database.Instance.query({ _id: { $nin: notToDelete } }, { _id: 1 }); const toDelete: string[] = (await toDeleteCursor.toArray()).map(doc => doc._id); toDeleteCursor.close(); - let i = 0; - let deleted = 0; - while (i < toDelete.length) { - const count = Math.min(toDelete.length, 5000); - const toDeleteDocs = toDelete.slice(i, i + count); - i += count; - const result = await Database.Instance.delete({ _id: { $in: toDeleteDocs } }, "newDocuments"); - deleted += result.deletedCount || 0; - } - // const result = await Database.Instance.delete({ _id: { $in: toDelete } }, "newDocuments"); - console.log(`${deleted} documents deleted`); + if (!full) { + await Database.Instance.updateMany({ _id: { $nin: notToDelete } }, { $set: { "deleted": true } }); + await Database.Instance.updateMany({ _id: { $in: notToDelete } }, { $unset: { "deleted": true } }); + console.log(await Search.Instance.updateDocuments( + notToDelete.map(id => ({ + id, deleted: { set: null } + })) + .concat(toDelete.map(id => ({ + id, deleted: { set: true } + }))))); + console.log("Done with partial GC"); + console.log(`Took ${(Date.now() - start) / 1000} seconds`); + } else { + let i = 0; + let deleted = 0; + while (i < toDelete.length) { + const count = Math.min(toDelete.length, 5000); + const toDeleteDocs = toDelete.slice(i, i + count); + i += count; + const result = await Database.Instance.delete({ _id: { $in: toDeleteDocs } }, "newDocuments"); + deleted += result.deletedCount || 0; + } + // const result = await Database.Instance.delete({ _id: { $in: toDelete } }, "newDocuments"); + console.log(`${deleted} documents deleted`); - await Search.Instance.deleteDocuments(toDelete); - console.log("Cleared search documents"); + await Search.Instance.deleteDocuments(toDelete); + console.log("Cleared search documents"); - const folder = "./src/server/public/files/"; - fs.readdir(folder, (_, fileList) => { - const filesToDelete = fileList.filter(file => { - const ext = path.extname(file); - let base = path.basename(file, ext); - const existsInDb = (base in files || (base = base.substring(0, base.length - 2)) in files) && files[base].includes(ext); - return file !== ".gitignore" && !existsInDb; - }); - console.log(`Deleting ${filesToDelete.length} files`); - filesToDelete.forEach(file => { - console.log(`Deleting file ${file}`); - try { - fs.unlinkSync(folder + file); - } catch { - console.warn(`Couldn't delete file ${file}`); - } + const folder = "./src/server/public/files/"; + fs.readdir(folder, (_, fileList) => { + const filesToDelete = fileList.filter(file => { + const ext = path.extname(file); + let base = path.basename(file, ext); + const existsInDb = (base in files || (base = base.substring(0, base.length - 2)) in files) && files[base].includes(ext); + return file !== ".gitignore" && !existsInDb; + }); + console.log(`Deleting ${filesToDelete.length} files`); + filesToDelete.forEach(file => { + console.log(`Deleting file ${file}`); + try { + fs.unlinkSync(folder + file); + } catch { + console.warn(`Couldn't delete file ${file}`); + } + }); + console.log(`Deleted ${filesToDelete.length} files`); }); - console.log(`Deleted ${filesToDelete.length} files`); - }); + } } -GarbageCollect(); +GarbageCollect(false); -- cgit v1.2.3-70-g09d2 From 189bb0ffd14fb0b8db0edbe813efe19f143a30fd Mon Sep 17 00:00:00 2001 From: monikahedman Date: Tue, 16 Jul 2019 14:46:44 -0400 Subject: shes fixed --- src/client/views/search/SearchBox.tsx | 1 + 1 file changed, 1 insertion(+) (limited to 'src/client/views/search') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 661c9c10b..0b2d792e0 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -94,6 +94,7 @@ export class SearchBox extends React.Component { this._results = []; this._isSearch = []; this._visibleElements = []; + FilterBox.Instance.closeFilter(); //if there is no query there should be no result if (query === "") { -- cgit v1.2.3-70-g09d2 From ecbae6521dde8e7e973b8d5f4e826746ea21a665 Mon Sep 17 00:00:00 2001 From: monikahedman Date: Tue, 16 Jul 2019 14:48:48 -0400 Subject: fixed AGAIN --- src/client/views/search/FilterBox.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/FilterBox.tsx b/src/client/views/search/FilterBox.tsx index f28b074a7..706d1eb7f 100644 --- a/src/client/views/search/FilterBox.tsx +++ b/src/client/views/search/FilterBox.tsx @@ -170,7 +170,7 @@ export class FilterBox extends React.Component { return finalQuery; } - get fieldFiltersApplied() { return !(this._deletedDocsStatus && this._authorFieldStatus && this._titleFieldStatus); } + get fieldFiltersApplied() { return !(this._authorFieldStatus && this._titleFieldStatus); } //TODO: basically all of this //gets all of the collections of all the docviews that are selected -- cgit v1.2.3-70-g09d2 From 6353522fbd8dc961b9c172b15d33af842fdab323 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 16 Jul 2019 17:03:41 -0400 Subject: Added deduplication of results --- src/client/views/search/SearchBox.tsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 04db26aca..cb4aef961 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -24,6 +24,7 @@ export class SearchBox extends React.Component { @observable private _resultsOpen: boolean = false; @observable private _searchbarOpen: boolean = false; @observable private _results: Doc[] = []; + private _resultsSet = new Set(); @observable private _openNoResults: boolean = false; @observable private _visibleElements: JSX.Element[] = []; @@ -61,6 +62,7 @@ export class SearchBox extends React.Component { this._openNoResults = false; this._results = []; + this._resultsSet.clear(); this._visibleElements = []; this._numTotalResults = -1; this._endIndex = -1; @@ -92,6 +94,7 @@ export class SearchBox extends React.Component { let query = this._searchString; query = FilterBox.Instance.getFinalQuery(query); this._results = []; + this._resultsSet.clear(); this._isSearch = []; this._visibleElements = []; @@ -120,7 +123,7 @@ export class SearchBox extends React.Component { private get filterQuery() { const types = FilterBox.Instance.filterTypes; - const includeDeleted = false; + const includeDeleted = FilterBox.Instance.getDataStatus(); return "NOT baseProto_b:true" + (includeDeleted ? "" : " AND NOT deleted:true") + (types ? ` AND (${types.map(type => `({!join from=id to=proto_i}type_t:"${type}" AND NOT type_t:*) OR type_t:"${type}"`).join(" ")})` : ""); } @@ -142,7 +145,13 @@ export class SearchBox extends React.Component { const docs = await Promise.all(res.docs.map(doc => Cast(doc.extendsDoc, Doc, doc as any))); let filteredDocs = FilterBox.Instance.filterDocsByType(docs); runInAction(() => { - this._results.push(...filteredDocs); + // this._results.push(...filteredDocs); + filteredDocs.forEach(doc => { + if (!this._resultsSet.has(doc)) { + this._results.push(doc); + this._resultsSet.add(doc); + } + }); }); this._curRequest = undefined; @@ -219,6 +228,7 @@ export class SearchBox extends React.Component { closeResults() { this._resultsOpen = false; this._results = []; + this._resultsSet.clear(); this._visibleElements = []; this._numTotalResults = -1; this._endIndex = -1; -- cgit v1.2.3-70-g09d2 From 31d2d8e058e0559707da352defd02585a3963353 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 16 Jul 2019 18:36:51 -0400 Subject: Added more parameters to and refactored search --- src/client/util/SearchUtil.ts | 37 ++++++++++++++-------- .../views/collections/ParentDocumentSelector.tsx | 4 +-- src/client/views/search/SearchBox.tsx | 16 ++++++---- src/client/views/search/SearchItem.scss | 12 ++++--- src/client/views/search/SearchItem.tsx | 10 ++++-- src/server/Search.ts | 12 ++----- src/server/database.ts | 11 +++++++ src/server/index.ts | 7 ++-- src/server/updateProtos.ts | 15 +++++++++ 9 files changed, 83 insertions(+), 41 deletions(-) create mode 100644 src/server/updateProtos.ts (limited to 'src/client/views/search') diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts index 806746496..abf1a7c32 100644 --- a/src/client/util/SearchUtil.ts +++ b/src/client/util/SearchUtil.ts @@ -4,30 +4,41 @@ import { Doc } from '../../new_fields/Doc'; import { Id } from '../../new_fields/FieldSymbols'; export namespace SearchUtil { + export type HighlightingResult = { [id: string]: { [key: string]: string[] } }; + export interface IdSearchResult { ids: string[]; numFound: number; + highlighting: HighlightingResult | undefined; } export interface DocSearchResult { docs: Doc[]; numFound: number; + highlighting: HighlightingResult | undefined; } - export function Search(query: string, filterQuery: string | undefined, returnDocs: true, start?: number, count?: number): Promise; - export function Search(query: string, filterQuery: string | undefined, returnDocs: false, start?: number, count?: number): Promise; - export async function Search(query: string, filterQuery: string | undefined, returnDocs: boolean, start?: number, rows?: number) { + export interface SearchParams { + hl?: boolean; + "hl.fl"?: string; + start?: number; + rows?: number; + fq?: string; + } + export function Search(query: string, returnDocs: true, options?: SearchParams): Promise; + export function Search(query: string, returnDocs: false, options?: SearchParams): Promise; + export async function Search(query: string, returnDocs: boolean, options: SearchParams = {}) { query = query || "*"; //If we just have a filter query, search for * as the query const result: IdSearchResult = JSON.parse(await rp.get(DocServer.prepend("/search"), { - qs: { query, filterQuery, start, rows }, + qs: { ...options, q: query }, })); if (!returnDocs) { return result; } - const { ids, numFound } = result; + const { ids, numFound, highlighting } = result; const docMap = await DocServer.GetRefFields(ids); const docs = ids.map((id: string) => docMap[id]).filter((doc: any) => doc instanceof Doc); - return { docs, numFound }; + return { docs, numFound, highlighting }; } export async function GetAliasesOfDocument(doc: Doc): Promise; @@ -36,31 +47,31 @@ export namespace SearchUtil { const proto = Doc.GetProto(doc); const protoId = proto[Id]; if (returnDocs) { - return (await Search("", `proto_i:"${protoId}"`, returnDocs)).docs; + return (await Search("", returnDocs, { fq: `proto_i:"${protoId}"` })).docs; } else { - return (await Search("", `proto_i:"${protoId}"`, returnDocs)).ids; + return (await Search("", returnDocs, { fq: `proto_i:"${protoId}"` })).ids; } // return Search(`{!join from=id to=proto_i}id:${protoId}`, true); } export async function GetViewsOfDocument(doc: Doc): Promise { - const results = await Search("", `proto_i:"${doc[Id]}"`, true); + const results = await Search("", true, { fq: `proto_i:"${doc[Id]}"` }); return results.docs; } export async function GetContextsOfDocument(doc: Doc): Promise<{ contexts: Doc[], aliasContexts: Doc[] }> { - const docContexts = (await Search("", `data_l:"${doc[Id]}"`, true)).docs; + const docContexts = (await Search("", true, { fq: `data_l:"${doc[Id]}"` })).docs; const aliases = await GetAliasesOfDocument(doc, false); - const aliasContexts = (await Promise.all(aliases.map(doc => Search("", `data_l:"${doc}"`, true)))); + const aliasContexts = (await Promise.all(aliases.map(doc => Search("", true, { fq: `data_l:"${doc}"` })))); const contexts = { contexts: docContexts, aliasContexts: [] as Doc[] }; aliasContexts.forEach(result => contexts.aliasContexts.push(...result.docs)); return contexts; } export async function GetContextIdsOfDocument(doc: Doc): Promise<{ contexts: string[], aliasContexts: string[] }> { - const docContexts = (await Search("", `data_l:"${doc[Id]}"`, false)).ids; + const docContexts = (await Search("", false, { fq: `data_l:"${doc[Id]}"` })).ids; const aliases = await GetAliasesOfDocument(doc, false); - const aliasContexts = (await Promise.all(aliases.map(doc => Search("", `data_l:"${doc}"`, false)))); + const aliasContexts = (await Promise.all(aliases.map(doc => Search("", false, { fq: `data_l:"${doc}"` })))); const contexts = { contexts: docContexts, aliasContexts: [] as string[] }; aliasContexts.forEach(result => contexts.aliasContexts.push(...result.ids)); return contexts; diff --git a/src/client/views/collections/ParentDocumentSelector.tsx b/src/client/views/collections/ParentDocumentSelector.tsx index a97aa4f36..c3e55d825 100644 --- a/src/client/views/collections/ParentDocumentSelector.tsx +++ b/src/client/views/collections/ParentDocumentSelector.tsx @@ -23,9 +23,9 @@ export class SelectorContextMenu extends React.Component { async fetchDocuments() { let aliases = (await SearchUtil.GetAliasesOfDocument(this.props.Document)).filter(doc => doc !== this.props.Document); - const { docs } = await SearchUtil.Search("", `data_l:"${this.props.Document[Id]}"`, true); + const { docs } = await SearchUtil.Search("", true, { fq: `data_l:"${this.props.Document[Id]}"` }); const map: Map = new Map; - const allDocs = await Promise.all(aliases.map(doc => SearchUtil.Search("", `data_l:"${doc[Id]}"`, true).then(result => result.docs))); + const allDocs = await Promise.all(aliases.map(doc => SearchUtil.Search("", true, { fq: `data_l:"${doc[Id]}"` }).then(result => result.docs))); allDocs.forEach((docs, index) => docs.forEach(doc => map.set(doc, aliases[index]))); docs.forEach(doc => map.delete(doc)); runInAction(() => { diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index d07df7e58..108492e90 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -23,7 +23,7 @@ export class SearchBox extends React.Component { @observable private _searchString: string = ""; @observable private _resultsOpen: boolean = false; @observable private _searchbarOpen: boolean = false; - @observable private _results: Doc[] = []; + @observable private _results: [Doc, string[]][] = []; private _resultsSet = new Set(); @observable private _openNoResults: boolean = false; @observable private _visibleElements: JSX.Element[] = []; @@ -119,7 +119,7 @@ export class SearchBox extends React.Component { } getAllResults = async (query: string) => { - return SearchUtil.Search(query, this.filterQuery, true, 0, 10000000); + return SearchUtil.Search(query, true, { fq: this.filterQuery, start: 0, rows: 10000000 }); } private get filterQuery() { @@ -136,20 +136,22 @@ 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, this.filterQuery, true, this._maxSearchIndex, 10).then(action(async (res: SearchUtil.DocSearchResult) => { + this._curRequest = SearchUtil.Search(query, true, { fq: this.filterQuery, start: this._maxSearchIndex, rows: 10, 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 highlighing = res.highlighting || {}; const docs = await Promise.all(res.docs.map(doc => Cast(doc.extendsDoc, Doc, doc as any))); let filteredDocs = FilterBox.Instance.filterDocsByType(docs); runInAction(() => { // this._results.push(...filteredDocs); filteredDocs.forEach(doc => { if (!this._resultsSet.has(doc)) { - this._results.push(doc); + const highlight = highlighing[doc[Id]]; + this._results.push([doc, highlight ? Object.keys(highlight).map(key => key.substring(0, key.length - 2)) : []]); this._resultsSet.add(doc); } }); @@ -274,19 +276,19 @@ export class SearchBox extends React.Component { } else { if (this._isSearch[i] !== "search") { - let result: Doc | undefined = undefined; + let result: [Doc, string[]] | undefined = undefined; if (i >= this._results.length) { this.getResults(this._searchString); if (i < this._results.length) result = this._results[i]; if (result) { - this._visibleElements[i] = ; + this._visibleElements[i] = ; this._isSearch[i] = "search"; } } else { result = this._results[i]; if (result) { - this._visibleElements[i] = ; + this._visibleElements[i] = ; this._isSearch[i] = "search"; } } diff --git a/src/client/views/search/SearchItem.scss b/src/client/views/search/SearchItem.scss index 24dd2eaa3..273d49349 100644 --- a/src/client/views/search/SearchItem.scss +++ b/src/client/views/search/SearchItem.scss @@ -24,11 +24,15 @@ flex-direction: row; width: 100%; - .search-title { - text-transform: uppercase; - text-align: left; + .search-title-container { width: 100%; - font-weight: bold; + + .search-title { + text-transform: uppercase; + text-align: left; + width: 100%; + font-weight: bold; + } } .search-info { diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx index e34d101a8..26f00e03e 100644 --- a/src/client/views/search/SearchItem.tsx +++ b/src/client/views/search/SearchItem.tsx @@ -26,6 +26,7 @@ import { faFile } from '@fortawesome/free-solid-svg-icons'; export interface SearchItemProps { doc: Doc; + highlighting: string[]; } library.add(faCaretUp); @@ -51,9 +52,9 @@ export class SelectorContextMenu extends React.Component { async fetchDocuments() { let aliases = (await SearchUtil.GetViewsOfDocument(this.props.doc)).filter(doc => doc !== this.props.doc); - const { docs } = await SearchUtil.Search("", `data_l:"${this.props.doc[Id]}"`, true); + const { docs } = await SearchUtil.Search("", true, { fq: `data_l:"${this.props.doc[Id]}"` }); const map: Map = new Map; - const allDocs = await Promise.all(aliases.map(doc => SearchUtil.Search("", `data_l:"${doc[Id]}"`, true).then(result => result.docs))); + const allDocs = await Promise.all(aliases.map(doc => SearchUtil.Search("", true, { fq: `data_l:"${doc[Id]}"` }).then(result => result.docs))); allDocs.forEach((docs, index) => docs.forEach(doc => map.set(doc, aliases[index]))); docs.forEach(doc => map.delete(doc)); runInAction(() => { @@ -243,7 +244,10 @@ export class SearchItem extends React.Component { onClick={this.onClick} onPointerDown={this.pointerDown} >
    -
    {StrCast(this.props.doc.title)}
    +
    +
    {StrCast(this.props.doc.title)}
    +
    Matched fields: {this.props.highlighting.join(", ")}
    +
    {this.DocumentIcon}
    diff --git a/src/server/Search.ts b/src/server/Search.ts index 69e327d2d..723dc101b 100644 --- a/src/server/Search.ts +++ b/src/server/Search.ts @@ -30,20 +30,14 @@ export class Search { } } - public async search(query: string, filterQuery: string = "", start: number = 0, rows: number = 10) { + public async search(query: any) { try { const searchResults = JSON.parse(await rp.get(this.url + "dash/select", { - qs: { - q: query, - fq: filterQuery, - fl: "id", - start, - rows, - } + qs: query })); const { docs, numFound } = searchResults.response; const ids = docs.map((field: any) => field.id); - return { ids, numFound }; + return { ids, numFound, highlighting: searchResults.highlighting }; } catch { return { ids: [], numFound: -1 }; } diff --git a/src/server/database.ts b/src/server/database.ts index 29a8ffafa..7f5331998 100644 --- a/src/server/database.ts +++ b/src/server/database.ts @@ -140,6 +140,17 @@ export class Database { } } + public updateMany(query: any, update: any, collectionName = "newDocuments") { + if (this.db) { + const db = this.db; + return new Promise(res => db.collection(collectionName).update(query, update, (_, result) => res(result))); + } else { + return new Promise(res => { + this.onConnect.push(() => this.updateMany(query, update, collectionName).then(res)); + }); + } + } + public print() { console.log("db says hi!"); } diff --git a/src/server/index.ts b/src/server/index.ts index 2cca7a35b..ad879093b 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -144,12 +144,13 @@ app.get("/pull", (req, res) => // GETTERS app.get("/search", async (req, res) => { - const { query, filterQuery, start, rows } = req.query; - if (query === undefined) { + const solrQuery: any = {}; + ["q", "fq", "start", "rows", "hl", "hl.fl"].forEach(key => solrQuery[key] = req.query[key]); + if (solrQuery.q === undefined) { res.send([]); return; } - let results = await Search.Instance.search(query, filterQuery, start, rows); + let results = await Search.Instance.search(solrQuery); res.send(results); }); diff --git a/src/server/updateProtos.ts b/src/server/updateProtos.ts new file mode 100644 index 000000000..90490eb45 --- /dev/null +++ b/src/server/updateProtos.ts @@ -0,0 +1,15 @@ +import { Database } from "./database"; + +const protos = + ["text", "histogram", "image", "web", "collection", "kvp", + "video", "audio", "pdf", "icon", "import", "linkdoc"]; + +(async function () { + await Promise.all( + protos.map(protoId => new Promise(res => Database.Instance.update(protoId, { + $set: { "fields.baseProto": true } + }, res))) + ); + + console.log("done"); +})(); \ No newline at end of file -- cgit v1.2.3-70-g09d2 From f0f020501c782a4989fc1dc47031acb40335532c Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 16 Jul 2019 22:26:18 -0400 Subject: Semi hacky fix for search matched fields with extensionDocs --- src/client/views/search/SearchBox.tsx | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'src/client/views/search') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 108492e90..8399605fb 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -24,7 +24,7 @@ export class SearchBox extends React.Component { @observable private _resultsOpen: boolean = false; @observable private _searchbarOpen: boolean = false; @observable private _results: [Doc, string[]][] = []; - private _resultsSet = new Set(); + private _resultsSet = new Map(); @observable private _openNoResults: boolean = false; @observable private _visibleElements: JSX.Element[] = []; @@ -143,16 +143,23 @@ export class SearchBox extends React.Component { this._numTotalResults = res.numFound; } - const highlighing = res.highlighting || {}; + const highlighting = res.highlighting || {}; + const highlightList = res.docs.map(doc => highlighting[doc[Id]]); const docs = await Promise.all(res.docs.map(doc => Cast(doc.extendsDoc, Doc, doc as any))); + const highlights: typeof res.highlighting = {}; + docs.forEach((doc, index) => highlights[doc[Id]] = highlightList[index]); let filteredDocs = FilterBox.Instance.filterDocsByType(docs); runInAction(() => { // this._results.push(...filteredDocs); filteredDocs.forEach(doc => { - if (!this._resultsSet.has(doc)) { - const highlight = highlighing[doc[Id]]; - this._results.push([doc, highlight ? Object.keys(highlight).map(key => key.substring(0, key.length - 2)) : []]); - this._resultsSet.add(doc); + const index = this._resultsSet.get(doc); + const highlight = highlights[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]); + } else { + this._results[index][1].push(...hlights); } }); }); -- cgit v1.2.3-70-g09d2 From de6e2427cf5eed2805432a37b5284a4c8b934e62 Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 17 Jul 2019 12:49:12 -0400 Subject: fixed some search box things. added more to audio annotations. --- package.json | 1 + src/client/views/nodes/ImageBox.tsx | 67 +++++++++++++++++++++++++++++++--- src/client/views/search/SearchBox.tsx | 2 +- src/client/views/search/SearchItem.tsx | 4 +- 4 files changed, 66 insertions(+), 8 deletions(-) (limited to 'src/client/views/search') diff --git a/package.json b/package.json index 7407a719f..2cec44473 100644 --- a/package.json +++ b/package.json @@ -129,6 +129,7 @@ "font-awesome": "^4.7.0", "formidable": "^1.2.1", "golden-layout": "^1.5.9", + "howler": "^2.1.2", "html-to-image": "^0.1.0", "i": "^0.3.6", "image-data-uri": "^2.0.0", diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 4c5ad7a7d..7c29724a2 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -1,6 +1,6 @@ import { library } from '@fortawesome/fontawesome-svg-core'; -import { faImage } from '@fortawesome/free-solid-svg-icons'; -import { action, observable, computed } from 'mobx'; +import { faImage, faFileAudio } from '@fortawesome/free-solid-svg-icons'; +import { action, observable, computed, runInAction } from 'mobx'; import { observer } from "mobx-react"; import Lightbox from 'react-image-lightbox'; import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app @@ -8,7 +8,7 @@ import { Doc, HeightSym, WidthSym, DocListCast } from '../../../new_fields/Doc'; import { List } from '../../../new_fields/List'; import { createSchema, listSpec, makeInterface } from '../../../new_fields/Schema'; import { Cast, FieldValue, NumCast, StrCast, BoolCast } from '../../../new_fields/Types'; -import { ImageField } from '../../../new_fields/URLField'; +import { ImageField, AudioField } from '../../../new_fields/URLField'; import { Utils } from '../../../Utils'; import { DragManager } from '../../util/DragManager'; import { undoBatch } from '../../util/UndoManager'; @@ -23,11 +23,15 @@ import React = require("react"); import { RouteStore } from '../../../server/RouteStore'; import { Docs } from '../../documents/Documents'; import { DocServer } from '../../DocServer'; +import { Font } from '@react-pdf/renderer'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; var requestImageSize = require('../../util/request-image-size'); var path = require('path'); +const { Howl, Howler } = require('howler'); library.add(faImage); +library.add(faFileAudio); export const pageSchema = createSchema({ @@ -177,10 +181,11 @@ export class ImageBox extends DocComponent(ImageD audioAnnos.push(audioDoc); } }; + runInAction(() => self._audioState = 2); recorder.start(); setTimeout(() => { recorder.stop(); - + runInAction(() => self._audioState = 0); gumStream.getAudioTracks()[0].stop(); }, 5000); }); @@ -272,6 +277,46 @@ export class ImageBox extends DocComponent(ImageD }); } + @observable _audioState = 0; + + @action + onPointerEnter = () => { + let self = this; + let audioAnnos = DocListCast(this.extensionDoc.audioAnnotations); + if (audioAnnos.length && this._audioState === 0) { + audioAnnos.map(anno => anno.data instanceof AudioField && new Howl({ + src: [anno.data.url.href], + autoplay: true, + loop: false, + volume: 0.5, + onend: function () { + runInAction(() => self._audioState = 0); + } + })); + this._audioState = 1; + } + else { + if (this._audioState === 0) { + this._audioState = 1; + new Howl({ + src: ["https://www.kozco.com/tech/piano2-CoolEdit.mp3"], + autoplay: true, + loop: false, + volume: 0.5, + onend: function () { + runInAction(() => self._audioState = 0); + } + }); + } + } + } + + @action + audioDown = () => { + this.recordAudioAnnotation(); + } + + render() { // let transform = this.props.ScreenToLocalTransform().inverse(); let pw = typeof this.props.PanelWidth === "function" ? this.props.PanelWidth() : typeof this.props.PanelWidth === "number" ? (this.props.PanelWidth as any) as number : 50; @@ -282,7 +327,7 @@ export class ImageBox extends DocComponent(ImageD let id = (this.props as any).id; // bcz: used to set id = "isExpander" in templates.tsx let nativeWidth = FieldValue(this.Document.nativeWidth, pw); let nativeHeight = FieldValue(this.Document.nativeHeight, 0); - let paths: string[] = ["http://www.cs.brown.edu/~bcz/noImage.png"]; + let paths: string[] = [window.origin + RouteStore.corsProxy + "/" + "http://www.cs.brown.edu/~bcz/noImage.png"]; // this._curSuffix = ""; // if (w > 20) { Doc.UpdateDocumentExtensionForField(this.dataDoc, this.props.fieldKey); @@ -305,6 +350,7 @@ export class ImageBox extends DocComponent(ImageD return (
    (ImageD ref={this._imgRef} onError={this.onError} /> {paths.length > 1 ? this.dots(paths) : (null)} +
    + +
    {/* {this.lightbox(paths)} */}
    ); } diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 8399605fb..16c44225a 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -145,7 +145,7 @@ export class SearchBox extends React.Component { const highlighting = res.highlighting || {}; const highlightList = res.docs.map(doc => highlighting[doc[Id]]); - const docs = await Promise.all(res.docs.map(doc => Cast(doc.extendsDoc, Doc, doc as any))); + const docs = await Promise.all(res.docs.map(async doc => (await Cast(doc.extendsDoc, Doc)) || doc)); const highlights: typeof res.highlighting = {}; docs.forEach((doc, index) => highlights[doc[Id]] = highlightList[index]); let filteredDocs = FilterBox.Instance.filterDocsByType(docs); diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx index 26f00e03e..a995140e2 100644 --- a/src/client/views/search/SearchItem.tsx +++ b/src/client/views/search/SearchItem.tsx @@ -101,8 +101,8 @@ export class SearchItem extends React.Component { onClick = () => { // I dont think this is the best functionality because clicking the name of the collection does that. Change it back if you'd like - // DocumentManager.Instance.jumpToDocument(this.props.doc, false); - CollectionDockingView.Instance.AddRightSplit(this.props.doc, undefined); + DocumentManager.Instance.jumpToDocument(this.props.doc, false); + // CollectionDockingView.Instance.AddRightSplit(this.props.doc, undefined); } @observable _useIcons = true; @observable _displayDim = 50; -- cgit v1.2.3-70-g09d2 From 5aa6bcdd4e23bb9e9d05181d0dc6b638e45e397b Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Wed, 17 Jul 2019 20:48:14 -0400 Subject: Moved DocServer.prepend and changed how corsProxy works --- src/Utils.ts | 13 +++++ src/client/DocServer.ts | 8 ---- src/client/util/History.ts | 2 +- .../util/Import & Export/DirectoryImportBox.tsx | 4 +- src/client/util/SearchUtil.ts | 3 +- src/client/util/TooltipTextMenu.tsx | 8 ++-- src/client/views/MainView.tsx | 4 +- src/client/views/SearchBox.tsx | 3 +- .../views/collections/CollectionDockingView.tsx | 2 +- src/client/views/collections/CollectionSubView.tsx | 7 +-- src/client/views/nodes/DocumentView.tsx | 4 +- src/client/views/nodes/FormattedTextBox.tsx | 5 +- src/client/views/nodes/ImageBox.tsx | 6 +-- src/client/views/nodes/VideoBox.tsx | 4 +- src/client/views/pdf/PDFViewer.tsx | 55 +++++----------------- src/client/views/search/SearchBox.tsx | 6 +-- src/mobile/ImageUpload.tsx | 5 +- .../authentication/models/current_user_utils.ts | 5 +- src/server/index.ts | 2 +- 19 files changed, 65 insertions(+), 81 deletions(-) (limited to 'src/client/views/search') diff --git a/src/Utils.ts b/src/Utils.ts index e8a80bdc3..ac6d127cc 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -2,6 +2,7 @@ import v4 = require('uuid/v4'); import v5 = require("uuid/v5"); import { Socket } from 'socket.io'; import { Message } from './server/Message'; +import { RouteStore } from './server/RouteStore'; export class Utils { @@ -27,6 +28,18 @@ export class Utils { return { scale, translateX, translateY }; } + /** + * A convenience method. Prepends the full path (i.e. http://localhost:1050) to the + * requested extension + * @param extension the specified sub-path to append to the window origin + */ + public static prepend(extension: string): string { + return window.location.origin + extension; + } + public static CorsProxy(url: string): string { + return this.prepend(RouteStore.corsProxy + "/") + encodeURIComponent(url); + } + public static CopyText(text: string) { var textArea = document.createElement("textarea"); textArea.value = text; diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index 6737657c8..8c64d2b2f 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -47,14 +47,6 @@ export namespace DocServer { Utils.AddServerHandler(_socket, MessageStore.DeleteField, respondToDelete); Utils.AddServerHandler(_socket, MessageStore.DeleteFields, respondToDelete); } - /** - * A convenience method. Prepends the full path (i.e. http://localhost:1050) to the - * requested extension - * @param extension the specified sub-path to append to the window origin - */ - export function prepend(extension: string): string { - return window.location.origin + extension; - } function errorFunc(): never { throw new Error("Can't use DocServer without calling init first"); diff --git a/src/client/util/History.ts b/src/client/util/History.ts index cbf5b3fc8..e9ff21b22 100644 --- a/src/client/util/History.ts +++ b/src/client/util/History.ts @@ -129,7 +129,7 @@ export namespace HistoryUtil { function addStringifier(type: string, keys: string[], customStringifier?: (state: ParsedUrl, current: string) => string) { stringifiers[type] = state => { - let path = DocServer.prepend(`/${type}`); + let path = Utils.prepend(`/${type}`); if (customStringifier) { path = customStringifier(state, path); } diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx index c096e9ceb..75b0b52a7 100644 --- a/src/client/util/Import & Export/DirectoryImportBox.tsx +++ b/src/client/util/Import & Export/DirectoryImportBox.tsx @@ -98,12 +98,12 @@ export default class DirectoryImportBox extends React.Component runInAction(() => this.remaining++); - let prom = fetch(DocServer.prepend(RouteStore.upload), { + let prom = fetch(Utils.prepend(RouteStore.upload), { method: 'POST', body: formData }).then(async (res: Response) => { (await res.json()).map(action((file: any) => { - let docPromise = Docs.Get.DocumentFromType(type, DocServer.prepend(file), { nativeWidth: 300, width: 300, title: dropFileName }); + let docPromise = Docs.Get.DocumentFromType(type, Utils.prepend(file), { nativeWidth: 300, width: 300, title: dropFileName }); docPromise.then(doc => { doc && docs.push(doc) && runInAction(() => this.remaining--); }); diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts index abf1a7c32..ee5a83710 100644 --- a/src/client/util/SearchUtil.ts +++ b/src/client/util/SearchUtil.ts @@ -2,6 +2,7 @@ import * as rp from 'request-promise'; import { DocServer } from '../DocServer'; import { Doc } from '../../new_fields/Doc'; import { Id } from '../../new_fields/FieldSymbols'; +import { Utils } from '../../Utils'; export namespace SearchUtil { export type HighlightingResult = { [id: string]: { [key: string]: string[] } }; @@ -29,7 +30,7 @@ export namespace SearchUtil { export function Search(query: string, returnDocs: false, options?: SearchParams): Promise; export async function Search(query: string, returnDocs: boolean, options: SearchParams = {}) { query = query || "*"; //If we just have a filter query, search for * as the query - const result: IdSearchResult = JSON.parse(await rp.get(DocServer.prepend("/search"), { + const result: IdSearchResult = JSON.parse(await rp.get(Utils.prepend("/search"), { qs: { ...options, q: query }, })); if (!returnDocs) { diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index 309d19016..a4c053de2 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -19,7 +19,7 @@ import { CollectionDockingView } from "../views/collections/CollectionDockingVie import { DocumentManager } from "./DocumentManager"; import { Id } from "../../new_fields/FieldSymbols"; import { FormattedTextBoxProps } from "../views/nodes/FormattedTextBox"; -import { SelectionManager } from "./SelectionManager"; +import { Utils } from "../../Utils"; //appears above a selection of text in a RichTextBox to give user options such as Bold, Italics, etc. export class TooltipTextMenu { @@ -213,8 +213,8 @@ export class TooltipTextMenu { let link = node && node.marks.find(m => m.type.name === "link"); if (link) { let href: string = link.attrs.href; - if (href.indexOf(DocServer.prepend("/doc/")) === 0) { - let docid = href.replace(DocServer.prepend("/doc/"), ""); + if (href.indexOf(Utils.prepend("/doc/")) === 0) { + let docid = href.replace(Utils.prepend("/doc/"), ""); DocServer.GetRefField(docid).then(action((f: Opt) => { if (f instanceof Doc) { if (DocumentManager.Instance.getDocumentView(f)) { @@ -254,7 +254,7 @@ export class TooltipTextMenu { if (docView && docView.props.ContainingCollectionView) { proto.sourceContext = docView.props.ContainingCollectionView.props.Document; } - linkDoc instanceof Doc && this.makeLink(DocServer.prepend("/doc/" + linkDoc[Id]), ctrlKey ? "onRight" : "inTab"); + linkDoc instanceof Doc && this.makeLink(Utils.prepend("/doc/" + linkDoc[Id]), ctrlKey ? "onRight" : "inTab"); }), }, hideSource: false diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index ce7369220..94a4835a1 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -16,7 +16,7 @@ import { listSpec } from '../../new_fields/Schema'; import { Cast, FieldValue, NumCast, BoolCast, StrCast } from '../../new_fields/Types'; import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; import { RouteStore } from '../../server/RouteStore'; -import { emptyFunction, returnOne, returnTrue } from '../../Utils'; +import { emptyFunction, returnOne, returnTrue, Utils } from '../../Utils'; import { DocServer } from '../DocServer'; import { Docs } from '../documents/Documents'; import { SetupDrag } from '../util/DragManager'; @@ -433,7 +433,7 @@ export class MainView extends React.Component { return [ this.isSearchVisible ?
    : null,
    -
    +
    ]; } diff --git a/src/client/views/SearchBox.tsx b/src/client/views/SearchBox.tsx index 1b9be841f..33cb63df5 100644 --- a/src/client/views/SearchBox.tsx +++ b/src/client/views/SearchBox.tsx @@ -13,6 +13,7 @@ import { Docs } from '../documents/Documents'; import { SetupDrag } from '../util/DragManager'; import { SearchItem } from './search/SearchItem'; import "./SearchBox.scss"; +import { Utils } from '../../Utils'; library.add(faSearch); library.add(faObjectGroup); @@ -47,7 +48,7 @@ export class SearchBox extends React.Component { @action getResults = async (query: string) => { - let response = await rp.get(DocServer.prepend('/search'), { + let response = await rp.get(Utils.prepend('/search'), { qs: { query } diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index a193ff677..ba7903419 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -465,7 +465,7 @@ export class CollectionDockingView extends React.Component boolean; @@ -164,7 +165,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { } else { let path = window.location.origin + "/doc/"; if (text.startsWith(path)) { - let docid = text.replace(DocServer.prepend("/doc/"), "").split("?")[0]; + let docid = text.replace(Utils.prepend("/doc/"), "").split("?")[0]; DocServer.GetRefField(docid).then(f => { if (f instanceof Doc) { if (options.x || options.y) { f.x = options.x; f.y = options.y; } // should be in CollectionFreeFormView @@ -193,7 +194,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { if (item.kind === "string" && item.type.indexOf("uri") !== -1) { let str: string; let prom = new Promise(resolve => e.dataTransfer.items[i].getAsString(resolve)) - .then(action((s: string) => rp.head(DocServer.prepend(RouteStore.corsProxy + "/" + (str = s))))) + .then(action((s: string) => rp.head(Utils.CorsProxy(str = s)))) .then(result => { let type = result["content-type"]; if (type) { @@ -219,7 +220,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { }).then(async (res: Response) => { (await res.json()).map(action((file: any) => { let full = { ...options, nativeWidth: type.indexOf("video") !== -1 ? 600 : 300, width: 300, title: dropFileName }; - let path = DocServer.prepend(file); + let path = Utils.prepend(file); Docs.Get.DocumentFromType(type, path, full).then(doc => doc && this.props.addDocument(doc)); })); }); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 245dd319d..af1cc079b 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -557,13 +557,13 @@ export class DocumentView extends DocComponent(Docu }); cm.addItem({ description: "Center View", event: () => this.props.focus(this.props.Document, false), icon: "crosshairs" }); cm.addItem({ description: "Zoom to Document", event: () => this.props.focus(this.props.Document, true), icon: "search" }); - cm.addItem({ description: "Copy URL", event: () => Utils.CopyText(DocServer.prepend("/doc/" + this.props.Document[Id])), icon: "link" }); + cm.addItem({ description: "Copy URL", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "link" }); cm.addItem({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]), icon: "fingerprint" }); cm.addItem({ description: "Delete", event: this.deleteClicked, icon: "trash" }); type User = { email: string, userDocumentId: string }; let usersMenu: ContextMenuProps[] = []; try { - let stuff = await rp.get(DocServer.prepend(RouteStore.getUsers)); + let stuff = await rp.get(Utils.prepend(RouteStore.getUsers)); const users: User[] = JSON.parse(stuff); usersMenu = users.filter(({ email }) => email !== CurrentUserUtils.email).map(({ email, userDocumentId }) => ({ description: email, event: async () => { diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 066cc40e2..99801ecff 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -35,6 +35,7 @@ import "./FormattedTextBox.scss"; import React = require("react"); import { DateField } from '../../../new_fields/DateField'; import { thisExpression } from 'babel-types'; +import { Utils } from '../../../Utils'; library.add(faEdit); library.add(faSmile); @@ -311,8 +312,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe href = parent.childNodes[0].href ? parent.childNodes[0].href : parent.href; } if (href) { - if (href.indexOf(DocServer.prepend("/doc/")) === 0) { - this._linkClicked = href.replace(DocServer.prepend("/doc/"), "").split("?")[0]; + if (href.indexOf(Utils.prepend("/doc/")) === 0) { + this._linkClicked = href.replace(Utils.prepend("/doc/"), "").split("?")[0]; if (this._linkClicked) { DocServer.GetRefField(this._linkClicked).then(async linkDoc => { if (linkDoc instanceof Doc) { diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index ebe3732e6..4ffd265d7 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -165,12 +165,12 @@ export class ImageBox extends DocComponent(ImageD recorder.ondataavailable = async function (e: any) { const formData = new FormData(); formData.append("file", e.data); - const res = await fetch(DocServer.prepend(RouteStore.upload), { + const res = await fetch(Utils.prepend(RouteStore.upload), { method: 'POST', body: formData }); const files = await res.json(); - const url = DocServer.prepend(files[0]); + const url = Utils.prepend(files[0]); // upload to server with known URL let audioDoc = Docs.Create.AudioDocument(url, { title: "audio test", x: NumCast(self.props.Document.x), y: NumCast(self.props.Document.y), width: 200, height: 32 }); audioDoc.embed = true; @@ -327,7 +327,7 @@ export class ImageBox extends DocComponent(ImageD let id = (this.props as any).id; // bcz: used to set id = "isExpander" in templates.tsx let nativeWidth = FieldValue(this.Document.nativeWidth, pw); let nativeHeight = FieldValue(this.Document.nativeHeight, 0); - let paths: string[] = [window.origin + RouteStore.corsProxy + "/" + "http://www.cs.brown.edu/~bcz/noImage.png"]; + let paths: string[] = [Utils.CorsProxy("http://www.cs.brown.edu/~bcz/noImage.png")]; // this._curSuffix = ""; // if (w > 20) { Doc.UpdateDocumentExtensionForField(this.dataDoc, this.props.fieldKey); diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 8b8e500c4..0f2d18f6b 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -122,7 +122,7 @@ export class VideoBox extends DocComponent(VideoD public static async convertDataUri(imageUri: string, returnedFilename: string) { try { - let posting = DocServer.prepend(RouteStore.dataUriToImage); + let posting = Utils.prepend(RouteStore.dataUriToImage); const returnedUri = await rp.post(posting, { body: { uri: imageUri, @@ -164,7 +164,7 @@ export class VideoBox extends DocComponent(VideoD let filename = encodeURIComponent("snapshot" + this.props.Document.title + "_" + this.props.Document.curPage).replace(/\./g, ""); VideoBox.convertDataUri(dataUrl, filename).then(returnedFilename => { if (returnedFilename) { - let url = DocServer.prepend(returnedFilename); + let url = Utils.prepend(returnedFilename); let imageSummary = Docs.Create.ImageDocument(url, { x: NumCast(this.props.Document.x) + width, y: NumCast(this.props.Document.y), width: 150, height: height / width * 150, title: "--snapshot" + NumCast(this.props.Document.curPage) + " image-" diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 699a1ffd7..b7ded7e06 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -4,23 +4,18 @@ import * as Pdfjs from "pdfjs-dist"; import "pdfjs-dist/web/pdf_viewer.css"; import * as rp from "request-promise"; import { Dictionary } from "typescript-collections"; -import { Doc, DocListCast, HeightSym, Opt, WidthSym } from "../../../new_fields/Doc"; +import { Doc, DocListCast, Opt } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; import { List } from "../../../new_fields/List"; -import { BoolCast, Cast, NumCast, StrCast, FieldValue } from "../../../new_fields/Types"; -import { emptyFunction } from "../../../Utils"; -import { DocServer } from "../../DocServer"; -import { Docs, DocUtils, DocumentOptions } from "../../documents/Documents"; -import { DocumentManager } from "../../util/DocumentManager"; +import { Cast, NumCast, StrCast } from "../../../new_fields/Types"; +import { emptyFunction, Utils } from "../../../Utils"; +import { Docs, DocUtils } from "../../documents/Documents"; import { DragManager } from "../../util/DragManager"; -import { DocumentView } from "../nodes/DocumentView"; -import { PDFBox, handleBackspace } from "../nodes/PDFBox"; +import { PDFBox } from "../nodes/PDFBox"; import Page from "./Page"; import "./PDFViewer.scss"; import React = require("react"); -import PDFMenu from "./PDFMenu"; -import { UndoManager } from "../../util/UndoManager"; -import { CompileScript, CompiledScript, CompileResult } from "../../util/Scripting"; +import { CompileScript, CompileResult } from "../../util/Scripting"; import { ScriptField } from "../../../new_fields/ScriptField"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import Annotation from "./Annotation"; @@ -90,16 +85,12 @@ export class Viewer extends React.Component { private _annotationReactionDisposer?: IReactionDisposer; private _dropDisposer?: DragManager.DragDropDisposer; private _filterReactionDisposer?: IReactionDisposer; - private _activeReactionDisposer?: IReactionDisposer; private _viewer: React.RefObject; private _mainCont: React.RefObject; private _pdfViewer: any; // private _textContent: Pdfjs.TextContent[] = []; private _pdfFindController: any; private _searchString: string = ""; - private _rendered: boolean = false; - private _pageIndex: number = -1; - private _matchIndex: number = 0; constructor(props: IViewerProps) { super(props); @@ -135,23 +126,6 @@ export class Viewer extends React.Component { }, { fireImmediately: true }); - this._activeReactionDisposer = reaction( - () => this.props.parent.props.active(), - () => { - runInAction(() => { - if (!this.props.parent.props.active()) { - this._searching = false; - this._pdfFindController = null; - if (this._viewer.current) { - let cns = this._viewer.current.childNodes; - for (let i = cns.length - 1; i >= 0; i--) { - cns.item(i).remove(); - } - } - } - }); - } - ); if (this.props.parent.props.ContainingCollectionView) { this._filterReactionDisposer = reaction( @@ -346,7 +320,7 @@ export class Viewer extends React.Component { this._isPage[page] = "image"; const address = this.props.url; try { - let res = JSON.parse(await rp.get(DocServer.prepend(`/thumbnail${address.substring("files/".length, address.length - ".pdf".length)}-${page + 1}.PNG`))); + let res = JSON.parse(await rp.get(Utils.prepend(`/thumbnail${address.substring("files/".length, address.length - ".pdf".length)}-${page + 1}.PNG`))); runInAction(() => this._visibleElements[page] = ); @@ -476,7 +450,6 @@ export class Viewer extends React.Component { phraseSearch: true, query: searchString }); - this._rendered = true; }); container.addEventListener("pagerendered", () => { console.log("rendered"); @@ -488,7 +461,6 @@ export class Viewer extends React.Component { phraseSearch: true, query: searchString }); - this._rendered = true; }); } } @@ -563,7 +535,6 @@ export class Viewer extends React.Component { }); container.addEventListener("pagerendered", () => { console.log("rendered"); - this._rendered = true; }); this._pdfViewer.setDocument(this.props.pdf); this._pdfFindController = new PDFJSViewer.PDFFindController(this._pdfViewer); @@ -703,17 +674,17 @@ class SimpleLinkService { externalLinkRel: any = null; pdf: any = null; - navigateTo(dest: any) { } + navigateTo() { } - getDestinationHash(dest: any) { return "#"; } + getDestinationHash() { return "#"; } - getAnchorUrl(hash: any) { return "#"; } + getAnchorUrl() { return "#"; } - setHash(hash: any) { } + setHash() { } - executeNamedAction(action: any) { } + executeNamedAction() { } - cachePageRef(pageNum: any, pageRef: any) { } + cachePageRef() { } get pagesCount() { return this.pdf ? this.pdf.numPages : 0; diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 16c44225a..2214ac8af 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -9,12 +9,12 @@ import { Docs } from '../../documents/Documents'; import { NumCast, Cast } from '../../../new_fields/Types'; import { Doc } from '../../../new_fields/Doc'; import { SearchItem } from './SearchItem'; -import { DocServer } from '../../DocServer'; import * as rp from 'request-promise'; import { Id } from '../../../new_fields/FieldSymbols'; import { SearchUtil } from '../../util/SearchUtil'; import { RouteStore } from '../../../server/RouteStore'; import { FilterBox } from './FilterBox'; +import { Utils } from '../../../Utils'; @observer @@ -74,7 +74,7 @@ export class SearchBox extends React.Component { public static async convertDataUri(imageUri: string, returnedFilename: string) { try { - let posting = DocServer.prepend(RouteStore.dataUriToImage); + let posting = Utils.prepend(RouteStore.dataUriToImage); const returnedUri = await rp.post(posting, { body: { uri: imageUri, @@ -154,7 +154,7 @@ export class SearchBox extends React.Component { filteredDocs.forEach(doc => { const index = this._resultsSet.get(doc); const highlight = highlights[doc[Id]]; - const hlights = highlight ? Object.keys(highlight).map(key => key.substring(0, key.length - 2)) : [] + 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]); diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index a8f94b746..33a615cbf 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -11,6 +11,7 @@ import { listSpec } from '../new_fields/Schema'; import { List } from '../new_fields/List'; import { observer } from 'mobx-react'; import { observable } from 'mobx'; +import { Utils } from '../Utils'; @@ -57,7 +58,7 @@ class Uploader extends React.Component { this.status = "getting user document"; - const res = await rp.get(DocServer.prepend(RouteStore.getUserDocumentId)); + const res = await rp.get(Utils.prepend(RouteStore.getUserDocumentId)); if (!res) { throw new Error("No user id returned"); } @@ -104,6 +105,8 @@ class Uploader extends React.Component { } +DocServer.init(window.location.protocol, window.location.hostname, 4321, "image upload"); + ReactDOM.render(( ), diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index e796ccb43..1c52a3f11 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -12,6 +12,7 @@ import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; import { Cast, FieldValue, StrCast } from "../../../new_fields/Types"; import { RouteStore } from "../../RouteStore"; +import { Utils } from "../../../Utils"; export class CurrentUserUtils { private static curr_email: string; @@ -74,7 +75,7 @@ export class CurrentUserUtils { } public static loadCurrentUser() { - return rp.get(DocServer.prepend(RouteStore.getCurrUser)).then(response => { + return rp.get(Utils.prepend(RouteStore.getCurrUser)).then(response => { if (response) { const result: { id: string, email: string } = JSON.parse(response); return result; @@ -87,7 +88,7 @@ export class CurrentUserUtils { public static async loadUserDocument({ id, email }: { id: string, email: string }) { this.curr_id = id; this.curr_email = email; - await rp.get(DocServer.prepend(RouteStore.getUserDocumentId)).then(id => { + await rp.get(Utils.prepend(RouteStore.getUserDocumentId)).then(id => { if (id) { return DocServer.GetRefField(id).then(async field => { if (field instanceof Doc) { diff --git a/src/server/index.ts b/src/server/index.ts index b3859aa4f..6b4e59bfc 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -417,7 +417,7 @@ app.get(RouteStore.reset, getReset); app.post(RouteStore.reset, postReset); app.use(RouteStore.corsProxy, (req, res) => - req.pipe(request(req.url.substring(1))).pipe(res)); + req.pipe(request(decodeURIComponent(req.url.substring(1)))).pipe(res)); app.get(RouteStore.delete, (req, res) => { if (release) { -- cgit v1.2.3-70-g09d2