From 4929d8b562c4f6300053cfd7d9583106df75b221 Mon Sep 17 00:00:00 2001 From: eperelm2 Date: Tue, 18 Jul 2023 16:06:29 -0400 Subject: continued fixing merge --- src/client/views/FilterPanel.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 68d29942b..5d1e5c08d 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -198,7 +198,7 @@ export class FilterPanel extends React.Component {
- {/* */} +
-- cgit v1.2.3-70-g09d2 From a193bdcb4e3abbb41698ef1ed0f65ff8407c5bf4 Mon Sep 17 00:00:00 2001 From: eperelm2 Date: Wed, 19 Jul 2023 13:23:25 -0400 Subject: collapsing in filters works --- src/client/views/FilterPanel.tsx | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 5d1e5c08d..1ab7ab54e 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -17,6 +17,12 @@ import { CiCircleRemove } from 'react-icons/ci'; interface filterProps { rootDoc: Doc; } + +const handleCollapse = (currentHeader: string) => { + // this._chosenFacetsCollapse.set(currentHeader, true); + console.log("hi") +} + @observer export class FilterPanel extends React.Component { public static LayoutString(fieldKey: string) { @@ -108,12 +114,16 @@ export class FilterPanel extends React.Component { }; @observable _chosenFacets = new ObservableMap(); + @observable _chosenFacetsCollapse = new ObservableMap(); + @computed get activeFacets() { + console.log("chosen collpase " + this._chosenFacetsCollapse) const facets = new Map(this._chosenFacets); StrListCast(this.targetDoc?._childFilters).map(filter => facets.set(filter.split(Doc.FilterSep)[0], filter.split(Doc.FilterSep)[2] === 'match' ? 'text' : 'checkbox')); setTimeout(() => StrListCast(this.targetDoc?._childFilters).map(action(filter => this._chosenFacets.set(filter.split(Doc.FilterSep)[0], filter.split(Doc.FilterSep)[2] === 'match' ? 'text' : 'checkbox')))); return facets; } + /** * Responds to clicking the check box in the flyout menu */ @@ -141,6 +151,7 @@ export class FilterPanel extends React.Component { } else { this._chosenFacets.set(facetHeader, 'checkbox'); } + this._chosenFacetsCollapse.set(facetHeader, false) }; facetValues = (facetHeader: string) => { @@ -167,10 +178,11 @@ export class FilterPanel extends React.Component { return nonNumbers / facetValues.length > 0.1 ? facetValues.sort() : facetValues.sort((n1: string, n2: string) => Number(n1) - Number(n2)); }; + // need boolean that is true or false on click but individual to that specific header + render() { const options = this._allFacets.filter(facet => this.currentFacets.indexOf(facet) === -1).map(facet => ({ value: facet, label: facet })); - console.log("this is option " + options) - console.log("this is alll facets " + this._allFacets) + return (
@@ -197,14 +209,18 @@ export class FilterPanel extends React.Component { {facetHeader.charAt(0).toUpperCase() + facetHeader.slice(1)}
- +
{ + const collapseBoolValue = this._chosenFacetsCollapse.get(facetHeader) + this._chosenFacetsCollapse.set(facetHeader, !collapseBoolValue )})}> +
+
- - {this.displayFacetValueFilterUIs(this.activeFacets.get(facetHeader), facetHeader)} + { this._chosenFacetsCollapse.get(facetHeader) ? null : this.displayFacetValueFilterUIs(this.activeFacets.get(facetHeader), facetHeader) } + {/* */}
))} @@ -213,6 +229,7 @@ export class FilterPanel extends React.Component { } private displayFacetValueFilterUIs(type: string | undefined, facetHeader: string): React.ReactNode { + console.log("opening a specific " + this.activeFacets.get(facetHeader)) switch (type) { case 'text': return ( -- cgit v1.2.3-70-g09d2 From e29a26a5095bbf8f05d327b1bbefc991967c6f2b Mon Sep 17 00:00:00 2001 From: eperelm2 Date: Wed, 19 Jul 2023 15:58:19 -0400 Subject: filter - trying to work on removing --- src/client/views/FilterPanel.tsx | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 1ab7ab54e..12dbf691f 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -18,11 +18,6 @@ interface filterProps { rootDoc: Doc; } -const handleCollapse = (currentHeader: string) => { - // this._chosenFacetsCollapse.set(currentHeader, true); - console.log("hi") -} - @observer export class FilterPanel extends React.Component { public static LayoutString(fieldKey: string) { @@ -178,7 +173,7 @@ export class FilterPanel extends React.Component { return nonNumbers / facetValues.length > 0.1 ? facetValues.sort() : facetValues.sort((n1: string, n2: string) => Number(n1) - Number(n2)); }; - // need boolean that is true or false on click but individual to that specific header + // change css and make the currently selected filters appear at the top render() { const options = this._allFacets.filter(facet => this.currentFacets.indexOf(facet) === -1).map(facet => ({ value: facet, label: facet })); @@ -214,7 +209,10 @@ export class FilterPanel extends React.Component { this._chosenFacetsCollapse.set(facetHeader, !collapseBoolValue )})}> - +
this.activeFacets.delete(facetHeader)) + } > +
-- cgit v1.2.3-70-g09d2 From 054ca2c87ebd67f24ddf70e686f0188d6a4fa620 Mon Sep 17 00:00:00 2001 From: eperelm2 Date: Thu, 20 Jul 2023 11:58:23 -0400 Subject: filter - closing works w/o filters selected --- src/client/views/FilterPanel.tsx | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 12dbf691f..416843f14 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -209,9 +209,18 @@ export class FilterPanel extends React.Component { this._chosenFacetsCollapse.set(facetHeader, !collapseBoolValue )})}> -
this.activeFacets.delete(facetHeader)) - } > +
{ + + // delete this.activeFacets[facetHeader]; + this.activeFacets.delete(facetHeader) + this._chosenFacets.delete(facetHeader) + //console.log("TRYING SOMETHING NEW " + e.target.checked) + + } + ) + } + // onChange = {undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, 'check'), 'set filter')} + >
@@ -227,7 +236,7 @@ export class FilterPanel extends React.Component { } private displayFacetValueFilterUIs(type: string | undefined, facetHeader: string): React.ReactNode { - console.log("opening a specific " + this.activeFacets.get(facetHeader)) + console.log("im here") switch (type) { case 'text': return ( @@ -242,6 +251,7 @@ export class FilterPanel extends React.Component { /> ); case 'checkbox': + // console.log("checking") return this.facetValues(facetHeader).map(fval => { const facetValue = fval; return ( @@ -255,6 +265,9 @@ export class FilterPanel extends React.Component { } type={type} onChange={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, e.target.checked ? 'check' : 'remove'), 'set filter')} + onClick={undoable (e => + console.log("boolean value with " + facetValue + ":" + e.target.checked), 'set filter' + ) } /> {facetValue} -- cgit v1.2.3-70-g09d2 From f847b894e79a0914ea2864f07ece92ac90eab1de Mon Sep 17 00:00:00 2001 From: eperelm2 Date: Thu, 20 Jul 2023 13:10:01 -0400 Subject: filter - still working on closing --- src/client/views/FilterPanel.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 416843f14..da00ae255 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -110,6 +110,7 @@ export class FilterPanel extends React.Component { @observable _chosenFacets = new ObservableMap(); @observable _chosenFacetsCollapse = new ObservableMap(); + // @observable _currentFilters: string[] ; -- instatitae array to store the currently selected filters (Ex: #food ). remove these filters when removing @computed get activeFacets() { console.log("chosen collpase " + this._chosenFacetsCollapse) @@ -214,7 +215,9 @@ export class FilterPanel extends React.Component { // delete this.activeFacets[facetHeader]; this.activeFacets.delete(facetHeader) this._chosenFacets.delete(facetHeader) - //console.log("TRYING SOMETHING NEW " + e.target.checked) + // console.log("TRYING SOMETHING NEW " + e.target.checked) + + // check if the current values are apart of the this.facetValues(facetHeader).map(fval ... } ) @@ -236,7 +239,6 @@ export class FilterPanel extends React.Component { } private displayFacetValueFilterUIs(type: string | undefined, facetHeader: string): React.ReactNode { - console.log("im here") switch (type) { case 'text': return ( @@ -252,6 +254,7 @@ export class FilterPanel extends React.Component { ); case 'checkbox': // console.log("checking") + return this.facetValues(facetHeader).map(fval => { const facetValue = fval; return ( @@ -266,7 +269,7 @@ export class FilterPanel extends React.Component { type={type} onChange={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, e.target.checked ? 'check' : 'remove'), 'set filter')} onClick={undoable (e => - console.log("boolean value with " + facetValue + ":" + e.target.checked), 'set filter' + e.target.checked ? this._currentFilters.push(fval) : , 'set filter' ) } /> {facetValue} -- cgit v1.2.3-70-g09d2 From 50cb7d0981a71c2eb45fbecfc2befad94d431eaa Mon Sep 17 00:00:00 2001 From: eperelm2 Date: Fri, 21 Jul 2023 15:07:04 -0400 Subject: filter - stuck on cancelling out need to remove filters and stop them from showing up. --- src/client/views/FilterPanel.tsx | 43 ++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index da00ae255..4f4e39218 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -110,6 +110,7 @@ export class FilterPanel extends React.Component { @observable _chosenFacets = new ObservableMap(); @observable _chosenFacetsCollapse = new ObservableMap(); + @observable _removeBoolean = false; // @observable _currentFilters: string[] ; -- instatitae array to store the currently selected filters (Ex: #food ). remove these filters when removing @computed get activeFacets() { @@ -213,12 +214,21 @@ export class FilterPanel extends React.Component {
{ // delete this.activeFacets[facetHeader]; + // StrListCast(this.targetDoc._childFilters).find(filter => filter.split(Doc.FilterSep)[2] = 'remove') + // .find(filter => filter.split(Doc.FilterSep)[0] === facetHeader && filter.split(Doc.FilterSep)[1] == facetValue) + // ?.split(Doc.FilterSep)[2] === 'check' + // console.log("why cant i get this "+ console.log( StrListCast(this.targetDoc._childFilters) + // .find(filter => filter.split(Doc.FilterSep)[0] === facetHeader))) this.activeFacets.delete(facetHeader) this._chosenFacets.delete(facetHeader) + this._chosenFacetsCollapse.delete(facetHeader) + // this._removeBoolean = true + // setTimeout(() => {this._removeBoolean = false}, 1000 ) // console.log("TRYING SOMETHING NEW " + e.target.checked) // check if the current values are apart of the this.facetValues(facetHeader).map(fval ... + // SET UP BOOLEAN AND IF IT IS TRUE MEANS ITS CLICKED AND THEN ALL BOXES SHOULD BE UNCHECKED } ) } @@ -261,16 +271,33 @@ export class FilterPanel extends React.Component {
filter.split(Doc.FilterSep)[0] === facetHeader && filter.split(Doc.FilterSep)[1] == facetValue) - ?.split(Doc.FilterSep)[2] === 'check' + checked={ this._removeBoolean ? false : + StrListCast(this.targetDoc._childFilters) + .find(filter => filter.split(Doc.FilterSep)[0] === facetHeader && filter.split(Doc.FilterSep)[1] == facetValue) + ?.split(Doc.FilterSep)[2] === 'check' + } type={type} - onChange={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, e.target.checked ? 'check' : 'remove'), 'set filter')} - onClick={undoable (e => - e.target.checked ? this._currentFilters.push(fval) : , 'set filter' - ) } + onChange={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, e.target.checked ? 'check' : 'remove'), 'set filter')} + // onClick={undoable (e => + // e.target.checked ? this._currentFilters.push(fval) : , 'set filter' + // ) } + onClick = {action((e) => { + console.log("im here") + console.log( StrListCast(this.targetDoc._childFilters) + .find(filter => filter.split(Doc.FilterSep)[0] === facetHeader && filter.split(Doc.FilterSep)[1] == facetValue) + // ?.split(Doc.FilterSep)[2] === 'check' + ) + StrListCast(this.targetDoc._childFilters).find(filter => console.log(" rahhhhhh1 " + filter.split(Doc.FilterSep)[1] === facetValue)) + StrListCast(this.targetDoc._childFilters).find(filter => console.log(" rahhhhhh2 " + filter.split(Doc.FilterSep)[2]) ) + } + + // console.log("this is an experiment " + StrListCast(this.targetDoc._childFilters) + + ) + // undoable (e => console.log(" this is an experiment " + e.target.checked), 'set filter') + + } /> {facetValue}
-- cgit v1.2.3-70-g09d2 From b3c0db8e2d6f29b6b09474b8252760e95f80de95 Mon Sep 17 00:00:00 2001 From: eperelm2 Date: Mon, 24 Jul 2023 14:46:05 -0400 Subject: filter- fixed removable and css (collapse bugs) --- src/client/views/FilterPanel.scss | 6 ++ src/client/views/FilterPanel.tsx | 112 +++++++++++++++++++------------------- src/fields/Doc.ts | 1 + 3 files changed, 64 insertions(+), 55 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/views/FilterPanel.scss b/src/client/views/FilterPanel.scss index bb68afed3..bb1e79d11 100644 --- a/src/client/views/FilterPanel.scss +++ b/src/client/views/FilterPanel.scss @@ -209,6 +209,12 @@ font-size: 16; } + .filterBox-facetHeader-remove{ + // margin-left: auto; + float: right; + font-size: 16; + } + } diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 4f4e39218..c99967ef7 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -14,6 +14,8 @@ import { undoable } from '../util/UndoManager'; import { AiOutlineMinusSquare } from 'react-icons/ai'; import { CiCircleRemove } from 'react-icons/ci'; +//slight bug when you don't click on background canvas before creating filter and the you click on the canvas + interface filterProps { rootDoc: Doc; } @@ -103,6 +105,8 @@ export class FilterPanel extends React.Component { return { strings: Array.from(valueSet.keys()), rtFields }; } + + public removeFilter = (filterName: string) => { Doc.setDocFilter(this.targetDoc, filterName, undefined, 'remove'); Doc.setDocRangeFilter(this.targetDoc, filterName, undefined); @@ -110,11 +114,10 @@ export class FilterPanel extends React.Component { @observable _chosenFacets = new ObservableMap(); @observable _chosenFacetsCollapse = new ObservableMap(); - @observable _removeBoolean = false; - // @observable _currentFilters: string[] ; -- instatitae array to store the currently selected filters (Ex: #food ). remove these filters when removing + @observable _currentActiveFilters = new ObservableMap(); @computed get activeFacets() { - console.log("chosen collpase " + this._chosenFacetsCollapse) + // console.log("chosen collpase " + this._chosenFacetsCollapse) const facets = new Map(this._chosenFacets); StrListCast(this.targetDoc?._childFilters).map(filter => facets.set(filter.split(Doc.FilterSep)[0], filter.split(Doc.FilterSep)[2] === 'match' ? 'text' : 'checkbox')); setTimeout(() => StrListCast(this.targetDoc?._childFilters).map(action(filter => this._chosenFacets.set(filter.split(Doc.FilterSep)[0], filter.split(Doc.FilterSep)[2] === 'match' ? 'text' : 'checkbox')))); @@ -151,6 +154,25 @@ export class FilterPanel extends React.Component { this._chosenFacetsCollapse.set(facetHeader, false) }; + @action + sortingCurrentFacetValues = (facetHeader:string) => { + + let returnKeys = []; + + console.log("this is current filtes " + this._currentActiveFilters) + for (var key of this.facetValues(facetHeader)){ + console.log("key : " + key ) + if (this._currentActiveFilters.get(key)){ + console.log("pushing") + returnKeys.push(key) + }} + console.log("this is return keys " + returnKeys) + return returnKeys.toString(); + } + + + + facetValues = (facetHeader: string) => { const allCollectionDocs = new Set(); SearchBox.foreachRecursiveDoc(this.targetDocChildren, (depth: number, doc: Doc) => allCollectionDocs.add(doc)); @@ -175,7 +197,6 @@ export class FilterPanel extends React.Component { return nonNumbers / facetValues.length > 0.1 ? facetValues.sort() : facetValues.sort((n1: string, n2: string) => Number(n1) - Number(n2)); }; - // change css and make the currently selected filters appear at the top render() { const options = this._allFacets.filter(facet => this.currentFacets.indexOf(facet) === -1).map(facet => ({ value: facet, label: facet })); @@ -205,41 +226,37 @@ export class FilterPanel extends React.Component {
{facetHeader.charAt(0).toUpperCase() + facetHeader.slice(1)} -
-
{ + {/*
*/} +
{ const collapseBoolValue = this._chosenFacetsCollapse.get(facetHeader) this._chosenFacetsCollapse.set(facetHeader, !collapseBoolValue )})}> -
+ + + +
-
{ - - // delete this.activeFacets[facetHeader]; - // StrListCast(this.targetDoc._childFilters).find(filter => filter.split(Doc.FilterSep)[2] = 'remove') - // .find(filter => filter.split(Doc.FilterSep)[0] === facetHeader && filter.split(Doc.FilterSep)[1] == facetValue) - // ?.split(Doc.FilterSep)[2] === 'check' - // console.log("why cant i get this "+ console.log( StrListCast(this.targetDoc._childFilters) - // .find(filter => filter.split(Doc.FilterSep)[0] === facetHeader))) - this.activeFacets.delete(facetHeader) - this._chosenFacets.delete(facetHeader) - this._chosenFacetsCollapse.delete(facetHeader) - // this._removeBoolean = true - // setTimeout(() => {this._removeBoolean = false}, 1000 ) - // console.log("TRYING SOMETHING NEW " + e.target.checked) - - // check if the current values are apart of the this.facetValues(facetHeader).map(fval ... - - // SET UP BOOLEAN AND IF IT IS TRUE MEANS ITS CLICKED AND THEN ALL BOXES SHOULD BE UNCHECKED - } - ) - } - // onChange = {undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, 'check'), 'set filter')} - > -
-
- +
{ + for (var key of this.facetValues(facetHeader)){ + if (this._currentActiveFilters.get(key)){ + Doc.setDocFilter(this.targetDoc, facetHeader, key, 'remove') + this._currentActiveFilters.delete(facetHeader) + }} + + this.activeFacets.delete(facetHeader) + this._chosenFacets.delete(facetHeader) + this._chosenFacetsCollapse.delete(facetHeader) + + })} > + +
+ {/*
*/} +
- { this._chosenFacetsCollapse.get(facetHeader) ? null : this.displayFacetValueFilterUIs(this.activeFacets.get(facetHeader), facetHeader) } + { this._chosenFacetsCollapse.get(facetHeader) ? + this.sortingCurrentFacetValues(facetHeader) : this.displayFacetValueFilterUIs(this.activeFacets.get(facetHeader), facetHeader) } {/* */} ))} @@ -263,7 +280,6 @@ export class FilterPanel extends React.Component { /> ); case 'checkbox': - // console.log("checking") return this.facetValues(facetHeader).map(fval => { const facetValue = fval; @@ -271,7 +287,7 @@ export class FilterPanel extends React.Component {
filter.split(Doc.FilterSep)[0] === facetHeader && filter.split(Doc.FilterSep)[1] == facetValue) ?.split(Doc.FilterSep)[2] === 'check' @@ -279,25 +295,11 @@ export class FilterPanel extends React.Component { } type={type} onChange={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, e.target.checked ? 'check' : 'remove'), 'set filter')} - // onClick={undoable (e => - // e.target.checked ? this._currentFilters.push(fval) : , 'set filter' - // ) } - onClick = {action((e) => { - console.log("im here") - console.log( StrListCast(this.targetDoc._childFilters) - .find(filter => filter.split(Doc.FilterSep)[0] === facetHeader && filter.split(Doc.FilterSep)[1] == facetValue) - // ?.split(Doc.FilterSep)[2] === 'check' - ) - StrListCast(this.targetDoc._childFilters).find(filter => console.log(" rahhhhhh1 " + filter.split(Doc.FilterSep)[1] === facetValue)) - StrListCast(this.targetDoc._childFilters).find(filter => console.log(" rahhhhhh2 " + filter.split(Doc.FilterSep)[2]) ) - } - - // console.log("this is an experiment " + StrListCast(this.targetDoc._childFilters) - - ) - // undoable (e => console.log(" this is an experiment " + e.target.checked), 'set filter') - - } + onClick={undoable (e => + e.target.checked ? this._currentActiveFilters.set(fval, facetHeader) : this._currentActiveFilters.delete(facetHeader) , 'set filter' + ) } + + /> {facetValue}
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 5a8a6e4b6..770a72855 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1437,6 +1437,7 @@ export namespace Doc { // all documents with the specified value for the specified key are included/excluded // based on the modifiers :"check", "x", undefined export function setDocFilter(container: Opt, key: string, value: any, modifiers: 'remove' | 'match' | 'check' | 'x' | 'exists' | 'unset', toggle?: boolean, fieldPrefix?: string, append: boolean = true) { + console.log("in setDocFilter: key "+ key + "value " + value) if (!container) return; const filterField = '_' + (fieldPrefix ? fieldPrefix + '_' : '') + 'childFilters'; const childFilters = StrListCast(container[filterField]); -- cgit v1.2.3-70-g09d2 From 14032744483a7fc83d552ccbe263cf9ec487fa25 Mon Sep 17 00:00:00 2001 From: eperelm2 Date: Tue, 25 Jul 2023 12:30:07 -0400 Subject: filters - collapsing works (w/o ui improvement) --- src/client/views/FilterPanel.scss | 7 +++++++ src/client/views/FilterPanel.tsx | 26 +++++++++++++++----------- 2 files changed, 22 insertions(+), 11 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/views/FilterPanel.scss b/src/client/views/FilterPanel.scss index bb1e79d11..d774983a7 100644 --- a/src/client/views/FilterPanel.scss +++ b/src/client/views/FilterPanel.scss @@ -215,6 +215,13 @@ font-size: 16; } + + +} +.filterbox-collpasedAndActive{ + left:100px; + background-color: pink; + font-size: 100px; } diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index c99967ef7..4cfc02ff7 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -115,6 +115,9 @@ export class FilterPanel extends React.Component { @observable _chosenFacets = new ObservableMap(); @observable _chosenFacetsCollapse = new ObservableMap(); @observable _currentActiveFilters = new ObservableMap(); + @observable _collapseReturnKeys = new Array(); + + // let returnKeys = []; @computed get activeFacets() { // console.log("chosen collpase " + this._chosenFacetsCollapse) @@ -154,20 +157,16 @@ export class FilterPanel extends React.Component { this._chosenFacetsCollapse.set(facetHeader, false) }; + @action sortingCurrentFacetValues = (facetHeader:string) => { - - let returnKeys = []; - - console.log("this is current filtes " + this._currentActiveFilters) + for (var key of this.facetValues(facetHeader)){ console.log("key : " + key ) if (this._currentActiveFilters.get(key)){ - console.log("pushing") - returnKeys.push(key) + this._collapseReturnKeys.push(key) }} - console.log("this is return keys " + returnKeys) - return returnKeys.toString(); + return this._collapseReturnKeys.toString(); } @@ -241,7 +240,7 @@ export class FilterPanel extends React.Component { for (var key of this.facetValues(facetHeader)){ if (this._currentActiveFilters.get(key)){ Doc.setDocFilter(this.targetDoc, facetHeader, key, 'remove') - this._currentActiveFilters.delete(facetHeader) + this._currentActiveFilters.delete(key) }} this.activeFacets.delete(facetHeader) @@ -256,7 +255,9 @@ export class FilterPanel extends React.Component { { this._chosenFacetsCollapse.get(facetHeader) ? - this.sortingCurrentFacetValues(facetHeader) : this.displayFacetValueFilterUIs(this.activeFacets.get(facetHeader), facetHeader) } +
{this.sortingCurrentFacetValues(facetHeader)}
&& this._collapseReturnKeys.splice(0) + + : this.displayFacetValueFilterUIs(this.activeFacets.get(facetHeader), facetHeader) } {/* */} ))} @@ -296,7 +297,7 @@ export class FilterPanel extends React.Component { type={type} onChange={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, e.target.checked ? 'check' : 'remove'), 'set filter')} onClick={undoable (e => - e.target.checked ? this._currentActiveFilters.set(fval, facetHeader) : this._currentActiveFilters.delete(facetHeader) , 'set filter' + e.target.checked ? this._currentActiveFilters.set(fval, facetHeader) : this._currentActiveFilters.delete(fval) , 'set filter' ) } @@ -308,3 +309,6 @@ export class FilterPanel extends React.Component { } } } + + +// NEED TO LEARN HOW TO RESET FILTERS WHEN WEBPAGE IS RELOADED \ No newline at end of file -- cgit v1.2.3-70-g09d2 From b84d3851d3baeeb0e2da5d4bd2fde9c911697d21 Mon Sep 17 00:00:00 2001 From: eperelm2 Date: Tue, 25 Jul 2023 15:05:46 -0400 Subject: filter - working w/ css (looking for recommendations) --- src/client/views/FilterPanel.scss | 13 ++++++++++--- src/client/views/FilterPanel.tsx | 16 +++++++++++++--- 2 files changed, 23 insertions(+), 6 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/views/FilterPanel.scss b/src/client/views/FilterPanel.scss index d774983a7..7cf886e12 100644 --- a/src/client/views/FilterPanel.scss +++ b/src/client/views/FilterPanel.scss @@ -188,6 +188,8 @@ margin-bottom: 10px; margin-left: 5px; overflow: auto; + + } } @@ -218,11 +220,16 @@ } + .filterbox-collpasedAndActive{ - left:100px; - background-color: pink; - font-size: 100px; + // left:100px; + text-indent: 18px; + // background-color: pink; + font-size: 12px; + font-weight: bold; + } + diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 4cfc02ff7..b03e11f79 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -161,12 +161,21 @@ export class FilterPanel extends React.Component { @action sortingCurrentFacetValues = (facetHeader:string) => { + this._collapseReturnKeys.splice(0) + for (var key of this.facetValues(facetHeader)){ console.log("key : " + key ) if (this._currentActiveFilters.get(key)){ this._collapseReturnKeys.push(key) }} - return this._collapseReturnKeys.toString(); + // return "hello" + + return (
+ + {this._collapseReturnKeys.toString()} +
) + + } @@ -255,8 +264,9 @@ export class FilterPanel extends React.Component { { this._chosenFacetsCollapse.get(facetHeader) ? -
{this.sortingCurrentFacetValues(facetHeader)}
&& this._collapseReturnKeys.splice(0) - + //
{this.sortingCurrentFacetValues(facetHeader)}
&& this._collapseReturnKeys.splice(0) + this.sortingCurrentFacetValues(facetHeader) + // && this._collapseReturnKeys.splice(0) : this.displayFacetValueFilterUIs(this.activeFacets.get(facetHeader), facetHeader) } {/* */} -- cgit v1.2.3-70-g09d2 From 43670f51a7dd627deeb3612f1066e51871235f2d Mon Sep 17 00:00:00 2001 From: eperelm2 Date: Wed, 26 Jul 2023 15:35:59 -0400 Subject: filter - UI updates --- src/client/views/FilterPanel.scss | 1 + src/client/views/FilterPanel.tsx | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/views/FilterPanel.scss b/src/client/views/FilterPanel.scss index 7cf886e12..78e7904b8 100644 --- a/src/client/views/FilterPanel.scss +++ b/src/client/views/FilterPanel.scss @@ -215,6 +215,7 @@ // margin-left: auto; float: right; font-size: 16; + font-weight:bold; } diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index b03e11f79..b14e73208 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -11,7 +11,7 @@ import './FilterPanel.scss'; import { FieldView } from './nodes/FieldView'; import { SearchBox } from './search/SearchBox'; import { undoable } from '../util/UndoManager'; -import { AiOutlineMinusSquare } from 'react-icons/ai'; +import { AiOutlineMinusSquare, AiOutlinePlusSquare } from 'react-icons/ai'; import { CiCircleRemove } from 'react-icons/ci'; //slight bug when you don't click on background canvas before creating filter and the you click on the canvas @@ -172,7 +172,8 @@ export class FilterPanel extends React.Component { return (
- {this._collapseReturnKeys.toString()} + {this._collapseReturnKeys.join(', ') } + {/* .toString()} */}
) @@ -240,7 +241,7 @@ export class FilterPanel extends React.Component { const collapseBoolValue = this._chosenFacetsCollapse.get(facetHeader) this._chosenFacetsCollapse.set(facetHeader, !collapseBoolValue )})}> - + {this._chosenFacetsCollapse.get(facetHeader) ? : } -- cgit v1.2.3-70-g09d2 From 9447ee01d501b3db69358b5b1526e640f2c54531 Mon Sep 17 00:00:00 2001 From: eperelm2 Date: Thu, 27 Jul 2023 13:02:19 -0400 Subject: filter - commented out slider and narrowing moving forward: need to change observable map to computed values --- src/client/documents/Documents.ts | 7 ++++++- src/client/views/FilterPanel.tsx | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 5ef033e35..8cb4be72c 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -96,7 +96,7 @@ class NumInfo extends FInfo { class StrInfo extends FInfo { fieldType? = 'string'; values?: string[] = []; - constructor(d: string, readOnly?: boolean, values?: string[]) { + constructor(d: string, readOnly?: boolean, values?: string[], filterable?:boolean) { super(d, readOnly); this.values = values; } @@ -138,9 +138,14 @@ class DateInfo extends FInfo { fieldType? = 'date'; values?: DateField[] = []; } +class ListInfo extends FInfo { + fieldType? = 'list'; + values?: List[] = []; +} type BOOLt = BoolInfo | boolean; type NUMt = NumInfo | number; type STRt = StrInfo | string; +type LISTt = ListInfo | List; type DOCt = DocInfo | Doc; type DIMt = DimInfo | typeof DimUnit.Pixel | typeof DimUnit.Ratio; type PEVt = PEInfo | 'none' | 'all'; diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index b14e73208..ccd5253ff 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -117,6 +117,10 @@ export class FilterPanel extends React.Component { @observable _currentActiveFilters = new ObservableMap(); @observable _collapseReturnKeys = new Array(); + // @computed get _currentActiveFilters(){ + // return StrListCast(this.targetDoc.docFilters).map() + // } + // let returnKeys = []; @computed get activeFacets() { @@ -151,6 +155,40 @@ export class FilterPanel extends React.Component { if (facetHeader === 'text' || (facetValues.rtFields / allCollectionDocs.length > 0.1 && facetValues.strings.length > 20)) { this._chosenFacets.set(facetHeader, 'text'); } else if (facetHeader !== 'tags' && nonNumbers / facetValues.strings.length < 0.1) { + + // const ranged = Doc.readDocRangeFilter(targetDoc, facetHeader); + // const extendedMinVal = minVal - Math.min(1, Math.floor(Math.abs(maxVal - minVal) * 0.1)); + // const extendedMaxVal = Math.max(minVal + 1, maxVal + Math.min(1, Math.ceil(Math.abs(maxVal - minVal) * 0.05))); + // newFacet[newFacetField + '-min'] = ranged === undefined ? extendedMinVal : ranged[0]; + // newFacet[newFacetField + '-max'] = ranged === undefined ? extendedMaxVal : ranged[1]; + // const scriptText = `setDocRangeFilter(this?.target, "${facetHeader}", range)`; + + // newFacet = Docs.Create.SliderDocument({ + // title: facetHeader, + // system: true, + // target: targetDoc, + // _fitWidth: true, + // _height: 40, + // _stayInCollection: true, + // treeViewExpandedView: 'layout', + // _treeViewOpen: true, + // _forceActive: true, + // _overflow: 'visible', + // }); + // const newFacetField = Doc.LayoutFieldKey(newFacet); + // const ranged = Doc.readDocRangeFilter(targetDoc, facetHeader); + // Doc.GetProto(newFacet).type = DocumentType.COL; // forces item to show an open/close button instead ofa checkbox + // const extendedMinVal = minVal - Math.min(1, Math.floor(Math.abs(maxVal - minVal) * 0.1)); + // const extendedMaxVal = Math.max(minVal + 1, maxVal + Math.min(1, Math.ceil(Math.abs(maxVal - minVal) * 0.05))); + // newFacet[newFacetField + '-min'] = ranged === undefined ? extendedMinVal : ranged[0]; + // newFacet[newFacetField + '-max'] = ranged === undefined ? extendedMaxVal : ranged[1]; + // Doc.GetProto(newFacet)[newFacetField + '-minThumb'] = extendedMinVal; + // Doc.GetProto(newFacet)[newFacetField + '-maxThumb'] = extendedMaxVal; + // const scriptText = `setDocRangeFilter(this?.target, "${facetHeader}", range)`; + // newFacet.onThumbChanged = ScriptField.MakeScript(scriptText, { this: Doc.name, range: 'number' }); + // newFacet.data = ComputedField.MakeFunction(`readNumFacetData(self.target, self, "${FilterBox.targetDocChildKey}", "${facetHeader}")`); + + } else { this._chosenFacets.set(facetHeader, 'checkbox'); } -- cgit v1.2.3-70-g09d2 From af5377f0e5bc69488c1620ae72b960f2a0f5d8f9 Mon Sep 17 00:00:00 2001 From: eperelm2 Date: Mon, 31 Jul 2023 12:58:32 -0400 Subject: filters - fixed bug on reload --- package-lock.json | 91 ++++++++++++++++++++++++++++++++++++++-- src/client/views/FilterPanel.tsx | 47 +++++++++++++-------- 2 files changed, 118 insertions(+), 20 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/package-lock.json b/package-lock.json index 082531ea0..e08568816 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6902,12 +6902,97 @@ "strip-ansi": "^7.0.1" } }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, "strip-ansi": { "version": "7.1.0", "bundled": true, "requires": { "ansi-regex": "^6.0.1" } + }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + } + } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } } } }, @@ -8412,7 +8497,7 @@ } }, "string-width-cjs": { - "version": "npm:string-width@4.2.3", + "version": "npm:string-width-cjs@4.2.3", "bundled": true, "requires": { "emoji-regex": "^8.0.0", @@ -8435,7 +8520,7 @@ } }, "strip-ansi-cjs": { - "version": "npm:strip-ansi@6.0.1", + "version": "npm:strip-ansi-cjs@6.0.1", "bundled": true, "requires": { "ansi-regex": "^5.0.1" @@ -8594,7 +8679,7 @@ } }, "wrap-ansi-cjs": { - "version": "npm:wrap-ansi@7.0.0", + "version": "npm:wrap-ansi-cjs@7.0.0", "bundled": true, "requires": { "ansi-styles": "^4.0.0", diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index ccd5253ff..f85052ff2 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -89,6 +89,7 @@ export class FilterPanel extends React.Component { newarray = []; subDocs.forEach(t => { const facetVal = t[facetKey]; + // console.log("facetVal " + facetVal) if (facetVal instanceof RichTextField || typeof facetVal === 'string') rtFields++; facetVal !== undefined && valueSet.add(Field.toString(facetVal as Field)); (facetVal === true || facetVal == false) && valueSet.add(Field.toString(!facetVal)); @@ -102,6 +103,7 @@ export class FilterPanel extends React.Component { } // } // }); + return { strings: Array.from(valueSet.keys()), rtFields }; } @@ -114,14 +116,20 @@ export class FilterPanel extends React.Component { @observable _chosenFacets = new ObservableMap(); @observable _chosenFacetsCollapse = new ObservableMap(); - @observable _currentActiveFilters = new ObservableMap(); @observable _collapseReturnKeys = new Array(); - // @computed get _currentActiveFilters(){ - // return StrListCast(this.targetDoc.docFilters).map() - // } - // let returnKeys = []; + // this computed function gets the active filters and maps them to their headers + + @computed get currentActiveFilterz(){ + const filters = new Map(); + //this.targetDoc.docFilters + StrListCast(this.targetDoc?._childFilters).map(filter => filters.set(filter.split(Doc.FilterSep)[1] ,filter.split(Doc.FilterSep)[0] )) + console.log("what is wrong with filters " +filters ) + return filters + } + + // let returnKeys = []; @computed get activeFacets() { // console.log("chosen collpase " + this._chosenFacetsCollapse) @@ -202,11 +210,11 @@ export class FilterPanel extends React.Component { this._collapseReturnKeys.splice(0) for (var key of this.facetValues(facetHeader)){ - console.log("key : " + key ) - if (this._currentActiveFilters.get(key)){ + // console.log("key : " + key ) + if (this.currentActiveFilterz.get(key)){ + // console.log("WEREEE HERHEHHHHEHHHHEEE") this._collapseReturnKeys.push(key) }} - // return "hello" return (
@@ -273,12 +281,21 @@ export class FilterPanel extends React.Component {
{facetHeader.charAt(0).toUpperCase() + facetHeader.slice(1)} - {/*
*/}
{ + + for (const [key, value] of this.currentActiveFilterz) { + + console.log("NEW KEY " + key + "NEW VAL " + value); + + } + console.log("this is gather field values : " + this.gatherFieldValues(this.targetDocChildren, facetHeader)) + console.log("this is current facets: " + this.currentFacets) + + console.log("this is facet Header " + facetHeader + ". this is the get " + this.activeFacets.get(facetHeader)) const collapseBoolValue = this._chosenFacetsCollapse.get(facetHeader) this._chosenFacetsCollapse.set(facetHeader, !collapseBoolValue )})}> - + {this._chosenFacetsCollapse.get(facetHeader) ? : }
@@ -286,9 +303,8 @@ export class FilterPanel extends React.Component {
{ for (var key of this.facetValues(facetHeader)){ - if (this._currentActiveFilters.get(key)){ + if (this.currentActiveFilterz.get(key)){ Doc.setDocFilter(this.targetDoc, facetHeader, key, 'remove') - this._currentActiveFilters.delete(key) }} this.activeFacets.delete(facetHeader) @@ -332,6 +348,7 @@ export class FilterPanel extends React.Component { case 'checkbox': return this.facetValues(facetHeader).map(fval => { + const facetValue = fval; return (
@@ -345,10 +362,7 @@ export class FilterPanel extends React.Component { } type={type} onChange={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, e.target.checked ? 'check' : 'remove'), 'set filter')} - onClick={undoable (e => - e.target.checked ? this._currentActiveFilters.set(fval, facetHeader) : this._currentActiveFilters.delete(fval) , 'set filter' - ) } - + /> {facetValue} @@ -360,4 +374,3 @@ export class FilterPanel extends React.Component { } -// NEED TO LEARN HOW TO RESET FILTERS WHEN WEBPAGE IS RELOADED \ No newline at end of file -- cgit v1.2.3-70-g09d2 From ae1c61907b6ffd0f9949d0d697bdc941eb28b7e2 Mon Sep 17 00:00:00 2001 From: eperelm2 Date: Mon, 31 Jul 2023 15:41:53 -0400 Subject: filters - working on range --- src/client/views/FilterPanel.tsx | 16 ++++++++++------ src/fields/Doc.ts | 4 ++++ 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index f85052ff2..d6638df46 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -164,12 +164,16 @@ export class FilterPanel extends React.Component { this._chosenFacets.set(facetHeader, 'text'); } else if (facetHeader !== 'tags' && nonNumbers / facetValues.strings.length < 0.1) { - // const ranged = Doc.readDocRangeFilter(targetDoc, facetHeader); - // const extendedMinVal = minVal - Math.min(1, Math.floor(Math.abs(maxVal - minVal) * 0.1)); - // const extendedMaxVal = Math.max(minVal + 1, maxVal + Math.min(1, Math.ceil(Math.abs(maxVal - minVal) * 0.05))); - // newFacet[newFacetField + '-min'] = ranged === undefined ? extendedMinVal : ranged[0]; - // newFacet[newFacetField + '-max'] = ranged === undefined ? extendedMaxVal : ranged[1]; - // const scriptText = `setDocRangeFilter(this?.target, "${facetHeader}", range)`; + console.log("in this IF STATEMENE ") + + const ranged = Doc.readDocRangeFilter(this.targetDoc, facetHeader); + const extendedMinVal = minVal - Math.min(1, Math.floor(Math.abs(maxVal - minVal) * 0.1)); + const extendedMaxVal = Math.max(minVal + 1, maxVal + Math.min(1, Math.ceil(Math.abs(maxVal - minVal) * 0.05))); + // newFacet[newFacetField + '-min'] = ranged === undefined ? extendedMinVal : ranged[0]; + // newFacet[newFacetField + '-max'] = ranged === undefined ? extendedMaxVal : ranged[1]; + // const scriptText = `setDocRangeFilter(this?.target, "${facetHeader}", range)`; + Doc.setDocRangeFilter(this.targetDoc, facetHeader) + // newFacet = Docs.Create.SliderDocument({ // title: facetHeader, diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 203f455db..578ee1caa 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1416,14 +1416,18 @@ export namespace Doc { } export function setDocRangeFilter(container: Opt, key: string, range?: number[]) { if (!container) return; + const childFiltersByRanges = Cast(container._childFiltersByRanges, listSpec('string'), []); + console.log("hellllloooooooooooooooooooooooooo " + childFiltersByRanges.length) for (let i = 0; i < childFiltersByRanges.length; i += 3) { + console.log("inside if statement") if (childFiltersByRanges[i] === key) { childFiltersByRanges.splice(i, 3); break; } } if (range !== undefined) { + console.log("in doc.ts in set range filter") childFiltersByRanges.push(key); childFiltersByRanges.push(range[0].toString()); childFiltersByRanges.push(range[1].toString()); -- cgit v1.2.3-70-g09d2 From fde0f815b3459d39b642d66c1c4466d9a9504979 Mon Sep 17 00:00:00 2001 From: eperelm2 Date: Tue, 1 Aug 2023 12:53:35 -0400 Subject: filters - bobs comments for future changes --- src/client/views/FilterPanel.tsx | 115 +++++++++++++++++++++++++++++---------- 1 file changed, 86 insertions(+), 29 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index d6638df46..ce6e2b1f3 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -65,13 +65,35 @@ export class FilterPanel extends React.Component { return [...noviceFields, ...sortedKeys]; } + @computed get rangeFilters() { + return StrListCast(this.targetDoc?._childFiltersByRanges).filter((filter, i) => !( i % 3) ) + } + /** - * The current attributes selected to filter based on + * activeFilters( ) -- all filters that currently have a filter set on them in this document (ranges, and others) + * ["#tags::bob::check", "tags::joe::check", "width", "height"] */ @computed get activeFilters() { - return StrListCast(this.targetDoc?._childFilters); + return StrListCast(this.targetDoc?._childFilters).concat(this.rangeFilters); } + // + // activeFacetHeaders() - just the facet names, not the rest of the filter + // + // this wants to return all the filter facets that have an existing filter set on them in order to show them in the rendered panel + // this set may overlap the selectedFilters + // if the components reloads, these will still exist and be shown + + // ["#tags", "width", "height"] + // + @computed get currentActiveFilterz(){ // this.existingFilters + const filters = new Map(); + //this.targetDoc.docFilters + this.activeFilters.map(filter => filters.set(filter.split(Doc.FilterSep)[1] ,filter.split(Doc.FilterSep)[0] )) + console.log("what is wrong with filters " +filters ) + return filters + } + /** * @returns a string array of the current attributes */ @@ -114,36 +136,55 @@ export class FilterPanel extends React.Component { Doc.setDocRangeFilter(this.targetDoc, filterName, undefined); }; - @observable _chosenFacets = new ObservableMap(); + // @observable _chosenFacets = new ObservableMap(); @observable _chosenFacetsCollapse = new ObservableMap(); @observable _collapseReturnKeys = new Array(); // this computed function gets the active filters and maps them to their headers - @computed get currentActiveFilterz(){ - const filters = new Map(); - //this.targetDoc.docFilters - StrListCast(this.targetDoc?._childFilters).map(filter => filters.set(filter.split(Doc.FilterSep)[1] ,filter.split(Doc.FilterSep)[0] )) - console.log("what is wrong with filters " +filters ) - return filters - } - - // let returnKeys = []; + // + // activeRenderedFacetInfos() + // returns renderInfo for all user selected filters and for all existing filters set on the document + // Map("tags" => {"checkbox"}, + // "width" => {"rangs", domain:[1978,1992]}) + // + @computed get activeFacets() { // selectedFacetRenderInfo => []:{facetName, renderInfo}[] renderInfo: { renderType: text|range|... , minVal?: , maxVal?; } + + // return new Set( + // Array.from(new Set(Array.from(this.selectedFacetHeaders).concat(this.existingFacetHeaders))) + // .map(facetHeader => { --> getting exisitng filters and new filters that havent been selected but need to remove duplicates + // most of what facetClick did before ... + // minVal, maxvval... + // if (...) + // return {key: facet, renderType: "text"} + // else if (... numbers) return {key:facet, renderrType: range, extendedMinVal, maxval + // return + // return .. + // })) - @computed get activeFacets() { // console.log("chosen collpase " + this._chosenFacetsCollapse) - const facets = new Map(this._chosenFacets); - StrListCast(this.targetDoc?._childFilters).map(filter => facets.set(filter.split(Doc.FilterSep)[0], filter.split(Doc.FilterSep)[2] === 'match' ? 'text' : 'checkbox')); - setTimeout(() => StrListCast(this.targetDoc?._childFilters).map(action(filter => this._chosenFacets.set(filter.split(Doc.FilterSep)[0], filter.split(Doc.FilterSep)[2] === 'match' ? 'text' : 'checkbox')))); + const facets = new Map(); + this.activeFilters.map(filter => facets.set(filter.split(Doc.FilterSep)[0], filter.split(Doc.FilterSep)[2] === 'match' ? 'text' : 'checkbox')); + // setTimeout(() => StrListCast(this.targetDoc?._childFilters).map(action(filter => this._chosenFacets.set(filter.split(Doc.FilterSep)[0], filter.split(Doc.FilterSep)[2] === 'match' ? 'text' : 'checkbox')))); return facets; } + @observable selectedFacetHeaders = new Set(); + /** - * Responds to clicking the check box in the flyout menu + * user clicks on a filter facet because they want to see it. + * this adds this chosen filter to a set of user selected filters called: selectedFilters + * if this component reloads, then these filters will go away since they haven't been written to any Doc anywhere + * + * // this._selectedFacets.add(facetHeader); .. add to Set() not array */ @action - facetClick = (facetHeader: string) => { + facetClick = (facetHeader: string) => { // just when someone chooses a facet + + // return; + + if (!this.targetDoc) return; const allCollectionDocs = this.targetDocChildren; const facetValues = this.gatherFieldValues(this.targetDocChildren, facetHeader); @@ -161,18 +202,20 @@ export class FilterPanel extends React.Component { } }); if (facetHeader === 'text' || (facetValues.rtFields / allCollectionDocs.length > 0.1 && facetValues.strings.length > 20)) { - this._chosenFacets.set(facetHeader, 'text'); + // this._chosenFacets.set(facetHeader, 'text'); } else if (facetHeader !== 'tags' && nonNumbers / facetValues.strings.length < 0.1) { console.log("in this IF STATEMENE ") - const ranged = Doc.readDocRangeFilter(this.targetDoc, facetHeader); + const ranged = Doc.readDocRangeFilter(this.targetDoc, facetHeader); // not the filter range, but the zooomed in range on the filter const extendedMinVal = minVal - Math.min(1, Math.floor(Math.abs(maxVal - minVal) * 0.1)); const extendedMaxVal = Math.max(minVal + 1, maxVal + Math.min(1, Math.ceil(Math.abs(maxVal - minVal) * 0.05))); - // newFacet[newFacetField + '-min'] = ranged === undefined ? extendedMinVal : ranged[0]; + // this.targetDoc["year-min"] = 1978 + // // facetHeader == year + // this.targetDoc[newFacetField + '-min'] = ranged === undefined ? extendedMinVal : ranged[0]; // newFacet[newFacetField + '-max'] = ranged === undefined ? extendedMaxVal : ranged[1]; // const scriptText = `setDocRangeFilter(this?.target, "${facetHeader}", range)`; - Doc.setDocRangeFilter(this.targetDoc, facetHeader) + Doc.setDocRangeFilter(this.targetDoc, facetHeader, [extendedMinVal, extendedMaxVal] ) // newFacet = Docs.Create.SliderDocument({ @@ -202,7 +245,7 @@ export class FilterPanel extends React.Component { } else { - this._chosenFacets.set(facetHeader, 'checkbox'); + // this._chosenFacets.set(facetHeader, 'checkbox'); } this._chosenFacetsCollapse.set(facetHeader, false) }; @@ -279,7 +322,7 @@ export class FilterPanel extends React.Component {
- {Array.from(this.activeFacets.keys()).map(facetHeader => ( + {Array.from(this.activeFacets.keys()).map(facetHeader => ( // iterato over activeFacetRenderInfos ==> renderInfo which you can renderInfo.facetHeader
@@ -312,7 +355,7 @@ export class FilterPanel extends React.Component { }} this.activeFacets.delete(facetHeader) - this._chosenFacets.delete(facetHeader) + // this._chosenFacets.delete(facetHeader) this._chosenFacetsCollapse.delete(facetHeader) })} > @@ -326,7 +369,7 @@ export class FilterPanel extends React.Component { //
{this.sortingCurrentFacetValues(facetHeader)}
&& this._collapseReturnKeys.splice(0) this.sortingCurrentFacetValues(facetHeader) // && this._collapseReturnKeys.splice(0) - : this.displayFacetValueFilterUIs(this.activeFacets.get(facetHeader), facetHeader) } + : this.displayFacetValueFilterUIs(this.activeFacets.get(facetHeader), facetHeader) } // pass renderInfo from iterator {/* */}
))} @@ -336,8 +379,9 @@ export class FilterPanel extends React.Component { } private displayFacetValueFilterUIs(type: string | undefined, facetHeader: string): React.ReactNode { - switch (type) { - case 'text': + // displayFacetValueFilterUIs(renderIinfo) + switch (type /* renderInfo.type */ ) { + case 'text': // if (this.chosenFacets.get(facetHeader) === 'text') return ( { {facetValue}
); - }); + }) + // case 'range' + // return domain is number[] for min and max + // onChange = { ... Doc.setDocRangeFilter(this.targetDoc, facetHeader, [extendedMinVal, extendedMaxVal] ) } + // + // OR + + // return
+ // // domain is number[] for min and max + // + // Date: Tue, 1 Aug 2023 16:04:46 -0400 Subject: filter - made bobs comments with basic slider implementation --- src/client/views/FilterPanel.tsx | 349 ++++++++++++++++++++++++++------------- src/fields/Doc.ts | 4 +- 2 files changed, 233 insertions(+), 120 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index ce6e2b1f3..b7718c6a3 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -13,6 +13,8 @@ import { SearchBox } from './search/SearchBox'; import { undoable } from '../util/UndoManager'; import { AiOutlineMinusSquare, AiOutlinePlusSquare } from 'react-icons/ai'; import { CiCircleRemove } from 'react-icons/ci'; +import { Slider, Rail, Handles, Tracks, Ticks } from 'react-compound-slider'; +import { TooltipRail, Handle, Tick, Track } from './nodes/SliderBox-components'; //slight bug when you don't click on background canvas before creating filter and the you click on the canvas @@ -77,6 +79,14 @@ export class FilterPanel extends React.Component { return StrListCast(this.targetDoc?._childFilters).concat(this.rangeFilters); } + @computed get mapActiveFiltersToFacets() { + const filters = new Map(); + //this.targetDoc.docFilters + this.activeFilters.map(filter => filters.set(filter.split(Doc.FilterSep)[1] ,filter.split(Doc.FilterSep)[0] )) + console.log("what is wrong with filters " +filters ) + return filters + } + // // activeFacetHeaders() - just the facet names, not the rest of the filter // @@ -86,20 +96,31 @@ export class FilterPanel extends React.Component { // ["#tags", "width", "height"] // - @computed get currentActiveFilterz(){ // this.existingFilters - const filters = new Map(); - //this.targetDoc.docFilters - this.activeFilters.map(filter => filters.set(filter.split(Doc.FilterSep)[1] ,filter.split(Doc.FilterSep)[0] )) - console.log("what is wrong with filters " +filters ) - return filters + + @computed get activeFacetHeaders() { + const activeHeaders = new Array() + + this.activeFilters.map(filter => activeHeaders.push(filter.split(Doc.FilterSep)[0]) ) + + + return activeHeaders; } + + + // @computed get currentActiveFilterz(){ // this.existingFilters + // const filters = new Map(); + // //this.targetDoc.docFilters + // this.activeFilters.map(filter => filters.set(filter.split(Doc.FilterSep)[1] ,filter.split(Doc.FilterSep)[0] )) + // console.log("what is wrong with filters " +filters ) + // return filters + // } /** * @returns a string array of the current attributes */ - @computed get currentFacets() { - return this.activeFilters.map(filter => filter.split(Doc.FilterSep)[0]); - } + // @computed get currentFacets() { + // return this.activeFilters.map(filter => filter.split(Doc.FilterSep)[0]); + // } gatherFieldValues(childDocs: Doc[], facetKey: string) { const valueSet = new Set(); @@ -149,28 +170,68 @@ export class FilterPanel extends React.Component { // Map("tags" => {"checkbox"}, // "width" => {"rangs", domain:[1978,1992]}) // - @computed get activeFacets() { // selectedFacetRenderInfo => []:{facetName, renderInfo}[] renderInfo: { renderType: text|range|... , minVal?: , maxVal?; } - - // return new Set( - // Array.from(new Set(Array.from(this.selectedFacetHeaders).concat(this.existingFacetHeaders))) - // .map(facetHeader => { --> getting exisitng filters and new filters that havent been selected but need to remove duplicates - // most of what facetClick did before ... - // minVal, maxvval... - // if (...) - // return {key: facet, renderType: "text"} - // else if (... numbers) return {key:facet, renderrType: range, extendedMinVal, maxval - // return - // return .. - // })) - - // console.log("chosen collpase " + this._chosenFacetsCollapse) - const facets = new Map(); - this.activeFilters.map(filter => facets.set(filter.split(Doc.FilterSep)[0], filter.split(Doc.FilterSep)[2] === 'match' ? 'text' : 'checkbox')); - // setTimeout(() => StrListCast(this.targetDoc?._childFilters).map(action(filter => this._chosenFacets.set(filter.split(Doc.FilterSep)[0], filter.split(Doc.FilterSep)[2] === 'match' ? 'text' : 'checkbox')))); - return facets; + + @computed get activeRenderedFacetInfos(){ + + return new Set( + Array.from(new Set(Array.from(this._selectedFacetHeaders).concat(this.activeFacetHeaders))).map( + facetHeader => { + + const facetValues = this.gatherFieldValues(this.targetDocChildren, facetHeader); + + let nonNumbers = 0; + let minVal = Number.MAX_VALUE, + maxVal = -Number.MAX_VALUE; + facetValues.strings.map(val => { + const num = val ? Number(val) : Number.NaN; + if (Number.isNaN(num)) { + val && nonNumbers++; + } else { + minVal = Math.min(num, minVal); + maxVal = Math.max(num, maxVal); + } + }); + + + if (facetHeader === 'text' ){ + return {facetHeader: facetHeader, renderType: 'text'} + + } else if (facetHeader !== 'tags' && nonNumbers / facetValues.strings.length < 0.1){ + + const extendedMinVal = minVal - Math.min(1, Math.floor(Math.abs(maxVal - minVal) * 0.1)); + const extendedMaxVal = Math.max(minVal + 1, maxVal + Math.min(1, Math.ceil(Math.abs(maxVal - minVal) * 0.05))); + const ranged = Doc.readDocRangeFilter(this.targetDoc, facetHeader); // not the filter range, but the zooomed in range on the filter + return {facetHeader: facetHeader, renderType: 'range', domain: [extendedMinVal, extendedMaxVal], range: ranged ? ranged: [extendedMinVal, extendedMaxVal]} + + } else{ + return {facetHeader: facetHeader, renderType: 'checkbox'} + } + } + )) } - @observable selectedFacetHeaders = new Set(); + // @computed get activeFacets() { // selectedFacetRenderInfo => []:{facetName, renderInfo}[] renderInfo: { renderType: text|range|... , minVal?: , maxVal?; } + + // // return new Set( + // // Array.from(new Set(Array.from(this.selectedFacetHeaders).concat(this.existingFacetHeaders))) + // // .map(facetHeader => { --> getting exisitng filters and new filters that havent been selected but need to remove duplicates + // // most of what facetClick did before ... + // // minVal, maxvval... + // // if (...) + // // return {key: facet, renderType: "text"} + // // else if (... numbers) return {key:facet, renderrType: range, extendedMinVal, maxval + // // return + // // return .. + // // })) + + // // console.log("chosen collpase " + this._chosenFacetsCollapse) + // const facets = new Map(); + // this.activeFilters.map(filter => facets.set(filter.split(Doc.FilterSep)[0], filter.split(Doc.FilterSep)[2] === 'match' ? 'text' : 'checkbox')); + // // setTimeout(() => StrListCast(this.targetDoc?._childFilters).map(action(filter => this._chosenFacets.set(filter.split(Doc.FilterSep)[0], filter.split(Doc.FilterSep)[2] === 'match' ? 'text' : 'checkbox')))); + // return facets; + // } + + @observable _selectedFacetHeaders = new Set(); /** * user clicks on a filter facet because they want to see it. @@ -182,72 +243,74 @@ export class FilterPanel extends React.Component { @action facetClick = (facetHeader: string) => { // just when someone chooses a facet - // return; + this._selectedFacetHeaders.add(facetHeader); + return - if (!this.targetDoc) return; - const allCollectionDocs = this.targetDocChildren; - const facetValues = this.gatherFieldValues(this.targetDocChildren, facetHeader); - let nonNumbers = 0; - let minVal = Number.MAX_VALUE, - maxVal = -Number.MAX_VALUE; - facetValues.strings.map(val => { - const num = val ? Number(val) : Number.NaN; - if (Number.isNaN(num)) { - val && nonNumbers++; - } else { - minVal = Math.min(num, minVal); - maxVal = Math.max(num, maxVal); - } - }); - if (facetHeader === 'text' || (facetValues.rtFields / allCollectionDocs.length > 0.1 && facetValues.strings.length > 20)) { - // this._chosenFacets.set(facetHeader, 'text'); - } else if (facetHeader !== 'tags' && nonNumbers / facetValues.strings.length < 0.1) { - - console.log("in this IF STATEMENE ") - - const ranged = Doc.readDocRangeFilter(this.targetDoc, facetHeader); // not the filter range, but the zooomed in range on the filter - const extendedMinVal = minVal - Math.min(1, Math.floor(Math.abs(maxVal - minVal) * 0.1)); - const extendedMaxVal = Math.max(minVal + 1, maxVal + Math.min(1, Math.ceil(Math.abs(maxVal - minVal) * 0.05))); - // this.targetDoc["year-min"] = 1978 - // // facetHeader == year - // this.targetDoc[newFacetField + '-min'] = ranged === undefined ? extendedMinVal : ranged[0]; - // newFacet[newFacetField + '-max'] = ranged === undefined ? extendedMaxVal : ranged[1]; - // const scriptText = `setDocRangeFilter(this?.target, "${facetHeader}", range)`; - Doc.setDocRangeFilter(this.targetDoc, facetHeader, [extendedMinVal, extendedMaxVal] ) - - - // newFacet = Docs.Create.SliderDocument({ - // title: facetHeader, - // system: true, - // target: targetDoc, - // _fitWidth: true, - // _height: 40, - // _stayInCollection: true, - // treeViewExpandedView: 'layout', - // _treeViewOpen: true, - // _forceActive: true, - // _overflow: 'visible', - // }); - // const newFacetField = Doc.LayoutFieldKey(newFacet); - // const ranged = Doc.readDocRangeFilter(targetDoc, facetHeader); - // Doc.GetProto(newFacet).type = DocumentType.COL; // forces item to show an open/close button instead ofa checkbox - // const extendedMinVal = minVal - Math.min(1, Math.floor(Math.abs(maxVal - minVal) * 0.1)); - // const extendedMaxVal = Math.max(minVal + 1, maxVal + Math.min(1, Math.ceil(Math.abs(maxVal - minVal) * 0.05))); - // newFacet[newFacetField + '-min'] = ranged === undefined ? extendedMinVal : ranged[0]; - // newFacet[newFacetField + '-max'] = ranged === undefined ? extendedMaxVal : ranged[1]; - // Doc.GetProto(newFacet)[newFacetField + '-minThumb'] = extendedMinVal; - // Doc.GetProto(newFacet)[newFacetField + '-maxThumb'] = extendedMaxVal; - // const scriptText = `setDocRangeFilter(this?.target, "${facetHeader}", range)`; - // newFacet.onThumbChanged = ScriptField.MakeScript(scriptText, { this: Doc.name, range: 'number' }); - // newFacet.data = ComputedField.MakeFunction(`readNumFacetData(self.target, self, "${FilterBox.targetDocChildKey}", "${facetHeader}")`); + // if (!this.targetDoc) return; + // const allCollectionDocs = this.targetDocChildren; + // const facetValues = this.gatherFieldValues(this.targetDocChildren, facetHeader); + + // let nonNumbers = 0; + // let minVal = Number.MAX_VALUE, + // maxVal = -Number.MAX_VALUE; + // facetValues.strings.map(val => { + // const num = val ? Number(val) : Number.NaN; + // if (Number.isNaN(num)) { + // val && nonNumbers++; + // } else { + // minVal = Math.min(num, minVal); + // maxVal = Math.max(num, maxVal); + // } + // }); + // if (facetHeader === 'text' || (facetValues.rtFields / allCollectionDocs.length > 0.1 && facetValues.strings.length > 20)) { + // // this._chosenFacets.set(facetHeader, 'text'); + // } else if (facetHeader !== 'tags' && nonNumbers / facetValues.strings.length < 0.1) { + + // console.log("in this IF STATEMENE ") + + // const ranged = Doc.readDocRangeFilter(this.targetDoc, facetHeader); // not the filter range, but the zooomed in range on the filter + // const extendedMinVal = minVal - Math.min(1, Math.floor(Math.abs(maxVal - minVal) * 0.1)); + // const extendedMaxVal = Math.max(minVal + 1, maxVal + Math.min(1, Math.ceil(Math.abs(maxVal - minVal) * 0.05))); + // // this.targetDoc["year-min"] = 1978 + // // // facetHeader == year + // // this.targetDoc[newFacetField + '-min'] = ranged === undefined ? extendedMinVal : ranged[0]; + // // newFacet[newFacetField + '-max'] = ranged === undefined ? extendedMaxVal : ranged[1]; + // // const scriptText = `setDocRangeFilter(this?.target, "${facetHeader}", range)`; + // Doc.setDocRangeFilter(this.targetDoc, facetHeader, [extendedMinVal, extendedMaxVal] ) + + + // // newFacet = Docs.Create.SliderDocument({ + // // title: facetHeader, + // // system: true, + // // target: targetDoc, + // // _fitWidth: true, + // // _height: 40, + // // _stayInCollection: true, + // // treeViewExpandedView: 'layout', + // // _treeViewOpen: true, + // // _forceActive: true, + // // _overflow: 'visible', + // // }); + // // const newFacetField = Doc.LayoutFieldKey(newFacet); + // // const ranged = Doc.readDocRangeFilter(targetDoc, facetHeader); + // // Doc.GetProto(newFacet).type = DocumentType.COL; // forces item to show an open/close button instead ofa checkbox + // // const extendedMinVal = minVal - Math.min(1, Math.floor(Math.abs(maxVal - minVal) * 0.1)); + // // const extendedMaxVal = Math.max(minVal + 1, maxVal + Math.min(1, Math.ceil(Math.abs(maxVal - minVal) * 0.05))); + // // newFacet[newFacetField + '-min'] = ranged === undefined ? extendedMinVal : ranged[0]; + // // newFacet[newFacetField + '-max'] = ranged === undefined ? extendedMaxVal : ranged[1]; + // // Doc.GetProto(newFacet)[newFacetField + '-minThumb'] = extendedMinVal; + // // Doc.GetProto(newFacet)[newFacetField + '-maxThumb'] = extendedMaxVal; + // // const scriptText = `setDocRangeFilter(this?.target, "${facetHeader}", range)`; + // // newFacet.onThumbChanged = ScriptField.MakeScript(scriptText, { this: Doc.name, range: 'number' }); + // // newFacet.data = ComputedField.MakeFunction(`readNumFacetData(self.target, self, "${FilterBox.targetDocChildKey}", "${facetHeader}")`); - } else { - // this._chosenFacets.set(facetHeader, 'checkbox'); - } - this._chosenFacetsCollapse.set(facetHeader, false) + // } else { + // // this._chosenFacets.set(facetHeader, 'checkbox'); + // } + // this._chosenFacetsCollapse.set(facetHeader, false) }; @@ -256,12 +319,13 @@ export class FilterPanel extends React.Component { this._collapseReturnKeys.splice(0) - for (var key of this.facetValues(facetHeader)){ + for (var key of this.facetValues(facetHeader)){ // all filters currently set // console.log("key : " + key ) - if (this.currentActiveFilterz.get(key)){ + if (this.mapActiveFiltersToFacets.get(key)){ // work with the current filter selected // console.log("WEREEE HERHEHHHHEHHHHEEE") this._collapseReturnKeys.push(key) - }} + } + } return (
@@ -301,7 +365,8 @@ export class FilterPanel extends React.Component { render() { - const options = this._allFacets.filter(facet => this.currentFacets.indexOf(facet) === -1).map(facet => ({ value: facet, label: facet })); + // const options = this._allFacets.filter(facet => this.currentFacets.indexOf(facet) === -1).map(facet => ({ value: facet, label: facet })); + const options = this._allFacets.filter(facet => this.activeFacetHeaders.indexOf(facet) === -1).map(facet => ({ value: facet, label: facet })); return (
@@ -322,41 +387,42 @@ export class FilterPanel extends React.Component {
- {Array.from(this.activeFacets.keys()).map(facetHeader => ( // iterato over activeFacetRenderInfos ==> renderInfo which you can renderInfo.facetHeader + {Array.from(this.activeRenderedFacetInfos.keys()).map(renderInfo => ( // iterato over activeFacetRenderInfos ==> renderInfo which you can renderInfo.facetHeader
- {facetHeader.charAt(0).toUpperCase() + facetHeader.slice(1)} + {renderInfo.facetHeader.charAt(0).toUpperCase() + renderInfo.facetHeader.slice(1)}
{ - for (const [key, value] of this.currentActiveFilterz) { - - console.log("NEW KEY " + key + "NEW VAL " + value); - - } - console.log("this is gather field values : " + this.gatherFieldValues(this.targetDocChildren, facetHeader)) - console.log("this is current facets: " + this.currentFacets) - - console.log("this is facet Header " + facetHeader + ". this is the get " + this.activeFacets.get(facetHeader)) - const collapseBoolValue = this._chosenFacetsCollapse.get(facetHeader) - this._chosenFacetsCollapse.set(facetHeader, !collapseBoolValue )})}> + + const collapseBoolValue = this._chosenFacetsCollapse.get(renderInfo.facetHeader) + this._chosenFacetsCollapse.set(renderInfo.facetHeader, !collapseBoolValue )})}> - {this._chosenFacetsCollapse.get(facetHeader) ? : } + {this._chosenFacetsCollapse.get(renderInfo.facetHeader) ? : }
{ - for (var key of this.facetValues(facetHeader)){ - if (this.currentActiveFilterz.get(key)){ - Doc.setDocFilter(this.targetDoc, facetHeader, key, 'remove') + for (var key of this.facetValues(renderInfo.facetHeader)){ + if (this.mapActiveFiltersToFacets.get(key)){ + Doc.setDocFilter(this.targetDoc, renderInfo.facetHeader, key, 'remove') }} - this.activeFacets.delete(facetHeader) + if (renderInfo.facetHeader) + + this._selectedFacetHeaders.delete(renderInfo.facetHeader) + + // this.activeFacets.delete(renderInfo.facetHeader) // this._chosenFacets.delete(facetHeader) - this._chosenFacetsCollapse.delete(facetHeader) + this._chosenFacetsCollapse.delete(renderInfo.facetHeader) + + console.log("this is activeFilters " + this.activeFilters) + console.log("this is activeFacetHeaders " + this.activeFacetHeaders) + console.log("thsi is activeRenderedFacetInfos " + this.activeRenderedFacetInfos) + console.log("thsi is selected facet Headers " + this._selectedFacetHeaders ) })} > @@ -365,11 +431,11 @@ export class FilterPanel extends React.Component {
- { this._chosenFacetsCollapse.get(facetHeader) ? + { this._chosenFacetsCollapse.get(renderInfo.facetHeader) ? //
{this.sortingCurrentFacetValues(facetHeader)}
&& this._collapseReturnKeys.splice(0) - this.sortingCurrentFacetValues(facetHeader) + this.sortingCurrentFacetValues(renderInfo.facetHeader) // && this._collapseReturnKeys.splice(0) - : this.displayFacetValueFilterUIs(this.activeFacets.get(facetHeader), facetHeader) } // pass renderInfo from iterator + : this.displayFacetValueFilterUIs(renderInfo.renderType, renderInfo.facetHeader, renderInfo.domain, renderInfo.range ) } {/* */}
))} @@ -378,7 +444,7 @@ export class FilterPanel extends React.Component { ); } - private displayFacetValueFilterUIs(type: string | undefined, facetHeader: string): React.ReactNode { + private displayFacetValueFilterUIs(type: string | undefined, facetHeader: string, renderInfoDomain?: number[] | undefined, renderInfoRange?: number[] ): React.ReactNode { // displayFacetValueFilterUIs(renderIinfo) switch (type /* renderInfo.type */ ) { case 'text': // if (this.chosenFacets.get(facetHeader) === 'text') @@ -417,6 +483,55 @@ export class FilterPanel extends React.Component {
); }) + + case 'range': + console.log("in range") + + const domain = renderInfoDomain; + + if (domain){ + return( + Doc.setDocRangeFilter(this.targetDoc, facetHeader, values)} values={renderInfoRange!} > + {railProps => } + + {({ handles, activeHandleID, getHandleProps }) => ( +
+ {handles.map((handle, i) => { + // const value = i === 0 ? defaultValues[0] : defaultValues[1]; + return ( +
+ +
+ ); + })} +
+ )} +
+ + {({ tracks, getTrackProps }) => ( +
+ {tracks.map(({ id, source, target }) => ( + + ))} +
+ )} +
+ + {({ ticks }) => ( +
+ {ticks.map(tick => ( + val.toString()} /> + ))} +
+ )} +
+
+ ) + } + + + // case 'range' // return domain is number[] for min and max diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 578ee1caa..d07028ec2 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1414,11 +1414,10 @@ export namespace Doc { prevLayout === 'icon' && (doc.deiconifyLayout = undefined); doc.layout_fieldKey = deiconify || 'layout'; } - export function setDocRangeFilter(container: Opt, key: string, range?: number[]) { + export function setDocRangeFilter(container: Opt, key: string, range?: readonly number[]) { if (!container) return; const childFiltersByRanges = Cast(container._childFiltersByRanges, listSpec('string'), []); - console.log("hellllloooooooooooooooooooooooooo " + childFiltersByRanges.length) for (let i = 0; i < childFiltersByRanges.length; i += 3) { console.log("inside if statement") if (childFiltersByRanges[i] === key) { @@ -1441,7 +1440,6 @@ export namespace Doc { // all documents with the specified value for the specified key are included/excluded // based on the modifiers :"check", "x", undefined export function setDocFilter(container: Opt, key: string, value: any, modifiers: 'remove' | 'match' | 'check' | 'x' | 'exists' | 'unset', toggle?: boolean, fieldPrefix?: string, append: boolean = true) { - console.log("in setDocFilter: key "+ key + "value " + value) if (!container) return; const filterField = '_' + (fieldPrefix ? fieldPrefix + '_' : '') + 'childFilters'; const childFilters = StrListCast(container[filterField]); -- cgit v1.2.3-70-g09d2 From 8d85780411df77db6150b88f0d8272f495c7fdb1 Mon Sep 17 00:00:00 2001 From: eperelm2 Date: Wed, 2 Aug 2023 12:58:34 -0400 Subject: filter - slider works (w/o UI and collapse) --- src/client/views/FilterPanel.scss | 22 ++++ src/client/views/FilterPanel.tsx | 228 ++++++++++---------------------------- src/fields/Doc.ts | 19 +++- 3 files changed, 99 insertions(+), 170 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/views/FilterPanel.scss b/src/client/views/FilterPanel.scss index 78e7904b8..b18b01325 100644 --- a/src/client/views/FilterPanel.scss +++ b/src/client/views/FilterPanel.scss @@ -231,6 +231,28 @@ } +// .sliderBox-outerDiv { +// width: 30%;// width: calc(100% - 14px); // 14px accounts for handles that are at the max value of the slider that would extend outside the box +// height: 40; // height: 100%; +// border-radius: inherit; +// display: flex; +// flex-direction: column; +// position: relative; +// // background-color: yellow; +// .slider-tracks { +// top: 7px; +// position: relative; +// } +// .slider-ticks { +// position: relative; +// } +// .slider-handles { +// top: 7px; +// position: relative; +// } +// } + + diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index b7718c6a3..54f5122b4 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -83,7 +83,6 @@ export class FilterPanel extends React.Component { const filters = new Map(); //this.targetDoc.docFilters this.activeFilters.map(filter => filters.set(filter.split(Doc.FilterSep)[1] ,filter.split(Doc.FilterSep)[0] )) - console.log("what is wrong with filters " +filters ) return filters } @@ -99,22 +98,11 @@ export class FilterPanel extends React.Component { @computed get activeFacetHeaders() { const activeHeaders = new Array() - this.activeFilters.map(filter => activeHeaders.push(filter.split(Doc.FilterSep)[0]) ) return activeHeaders; } - - - // @computed get currentActiveFilterz(){ // this.existingFilters - // const filters = new Map(); - // //this.targetDoc.docFilters - // this.activeFilters.map(filter => filters.set(filter.split(Doc.FilterSep)[1] ,filter.split(Doc.FilterSep)[0] )) - // console.log("what is wrong with filters " +filters ) - // return filters - // } - /** * @returns a string array of the current attributes */ @@ -210,27 +198,6 @@ export class FilterPanel extends React.Component { )) } - // @computed get activeFacets() { // selectedFacetRenderInfo => []:{facetName, renderInfo}[] renderInfo: { renderType: text|range|... , minVal?: , maxVal?; } - - // // return new Set( - // // Array.from(new Set(Array.from(this.selectedFacetHeaders).concat(this.existingFacetHeaders))) - // // .map(facetHeader => { --> getting exisitng filters and new filters that havent been selected but need to remove duplicates - // // most of what facetClick did before ... - // // minVal, maxvval... - // // if (...) - // // return {key: facet, renderType: "text"} - // // else if (... numbers) return {key:facet, renderrType: range, extendedMinVal, maxval - // // return - // // return .. - // // })) - - // // console.log("chosen collpase " + this._chosenFacetsCollapse) - // const facets = new Map(); - // this.activeFilters.map(filter => facets.set(filter.split(Doc.FilterSep)[0], filter.split(Doc.FilterSep)[2] === 'match' ? 'text' : 'checkbox')); - // // setTimeout(() => StrListCast(this.targetDoc?._childFilters).map(action(filter => this._chosenFacets.set(filter.split(Doc.FilterSep)[0], filter.split(Doc.FilterSep)[2] === 'match' ? 'text' : 'checkbox')))); - // return facets; - // } - @observable _selectedFacetHeaders = new Set(); /** @@ -240,105 +207,40 @@ export class FilterPanel extends React.Component { * * // this._selectedFacets.add(facetHeader); .. add to Set() not array */ + @action facetClick = (facetHeader: string) => { // just when someone chooses a facet this._selectedFacetHeaders.add(facetHeader); return - - - // if (!this.targetDoc) return; - // const allCollectionDocs = this.targetDocChildren; - // const facetValues = this.gatherFieldValues(this.targetDocChildren, facetHeader); - - // let nonNumbers = 0; - // let minVal = Number.MAX_VALUE, - // maxVal = -Number.MAX_VALUE; - // facetValues.strings.map(val => { - // const num = val ? Number(val) : Number.NaN; - // if (Number.isNaN(num)) { - // val && nonNumbers++; - // } else { - // minVal = Math.min(num, minVal); - // maxVal = Math.max(num, maxVal); - // } - // }); - // if (facetHeader === 'text' || (facetValues.rtFields / allCollectionDocs.length > 0.1 && facetValues.strings.length > 20)) { - // // this._chosenFacets.set(facetHeader, 'text'); - // } else if (facetHeader !== 'tags' && nonNumbers / facetValues.strings.length < 0.1) { - - // console.log("in this IF STATEMENE ") - - // const ranged = Doc.readDocRangeFilter(this.targetDoc, facetHeader); // not the filter range, but the zooomed in range on the filter - // const extendedMinVal = minVal - Math.min(1, Math.floor(Math.abs(maxVal - minVal) * 0.1)); - // const extendedMaxVal = Math.max(minVal + 1, maxVal + Math.min(1, Math.ceil(Math.abs(maxVal - minVal) * 0.05))); - // // this.targetDoc["year-min"] = 1978 - // // // facetHeader == year - // // this.targetDoc[newFacetField + '-min'] = ranged === undefined ? extendedMinVal : ranged[0]; - // // newFacet[newFacetField + '-max'] = ranged === undefined ? extendedMaxVal : ranged[1]; - // // const scriptText = `setDocRangeFilter(this?.target, "${facetHeader}", range)`; - // Doc.setDocRangeFilter(this.targetDoc, facetHeader, [extendedMinVal, extendedMaxVal] ) - - - // // newFacet = Docs.Create.SliderDocument({ - // // title: facetHeader, - // // system: true, - // // target: targetDoc, - // // _fitWidth: true, - // // _height: 40, - // // _stayInCollection: true, - // // treeViewExpandedView: 'layout', - // // _treeViewOpen: true, - // // _forceActive: true, - // // _overflow: 'visible', - // // }); - // // const newFacetField = Doc.LayoutFieldKey(newFacet); - // // const ranged = Doc.readDocRangeFilter(targetDoc, facetHeader); - // // Doc.GetProto(newFacet).type = DocumentType.COL; // forces item to show an open/close button instead ofa checkbox - // // const extendedMinVal = minVal - Math.min(1, Math.floor(Math.abs(maxVal - minVal) * 0.1)); - // // const extendedMaxVal = Math.max(minVal + 1, maxVal + Math.min(1, Math.ceil(Math.abs(maxVal - minVal) * 0.05))); - // // newFacet[newFacetField + '-min'] = ranged === undefined ? extendedMinVal : ranged[0]; - // // newFacet[newFacetField + '-max'] = ranged === undefined ? extendedMaxVal : ranged[1]; - // // Doc.GetProto(newFacet)[newFacetField + '-minThumb'] = extendedMinVal; - // // Doc.GetProto(newFacet)[newFacetField + '-maxThumb'] = extendedMaxVal; - // // const scriptText = `setDocRangeFilter(this?.target, "${facetHeader}", range)`; - // // newFacet.onThumbChanged = ScriptField.MakeScript(scriptText, { this: Doc.name, range: 'number' }); - // // newFacet.data = ComputedField.MakeFunction(`readNumFacetData(self.target, self, "${FilterBox.targetDocChildKey}", "${facetHeader}")`); - - - // } else { - // // this._chosenFacets.set(facetHeader, 'checkbox'); - // } - // this._chosenFacetsCollapse.set(facetHeader, false) }; @action sortingCurrentFacetValues = (facetHeader:string) => { - + console.log("in function to begin with") this._collapseReturnKeys.splice(0) - for (var key of this.facetValues(facetHeader)){ // all filters currently set - // console.log("key : " + key ) - if (this.mapActiveFiltersToFacets.get(key)){ // work with the current filter selected - // console.log("WEREEE HERHEHHHHEHHHHEEE") - this._collapseReturnKeys.push(key) - } - } + console.log("this si sfacetValies " + this.facetValues(facetHeader)) - return (
- - {this._collapseReturnKeys.join(', ') } - {/* .toString()} */} -
) - + //if range then display range values + + // if(Array.from(this.activeRenderedFacetInfos.keys()).map(renderInfo => (renderInfo.renderType === "range" && renderInfo.facetHeader === facetHeader ))){ + // console.log("JOE MAMA") + // } + for (var key of this.facetValues(facetHeader)){ + if (this.mapActiveFiltersToFacets.get(key)){ + this._collapseReturnKeys.push(key) + }} + return ( +
+ {this._collapseReturnKeys.join(', ') } +
) } - - facetValues = (facetHeader: string) => { const allCollectionDocs = new Set(); SearchBox.foreachRecursiveDoc(this.targetDocChildren, (depth: number, doc: Doc) => allCollectionDocs.add(doc)); @@ -365,7 +267,6 @@ export class FilterPanel extends React.Component { render() { - // const options = this._allFacets.filter(facet => this.currentFacets.indexOf(facet) === -1).map(facet => ({ value: facet, label: facet })); const options = this._allFacets.filter(facet => this.activeFacetHeaders.indexOf(facet) === -1).map(facet => ({ value: facet, label: facet })); return ( @@ -410,19 +311,20 @@ export class FilterPanel extends React.Component { if (this.mapActiveFiltersToFacets.get(key)){ Doc.setDocFilter(this.targetDoc, renderInfo.facetHeader, key, 'remove') }} - - if (renderInfo.facetHeader) - this._selectedFacetHeaders.delete(renderInfo.facetHeader) - - // this.activeFacets.delete(renderInfo.facetHeader) - // this._chosenFacets.delete(facetHeader) this._chosenFacetsCollapse.delete(renderInfo.facetHeader) + Doc.setDocRangeFilter(this.targetDoc, renderInfo.facetHeader, renderInfo.domain, 'remove') + + console.log("this is activeFilters " + this.activeFilters) console.log("this is activeFacetHeaders " + this.activeFacetHeaders) console.log("thsi is activeRenderedFacetInfos " + this.activeRenderedFacetInfos) console.log("thsi is selected facet Headers " + this._selectedFacetHeaders ) + console.log("THIS IS THE ONE ADDED "+ this.targetDoc?._childFiltersByRanges) + + + })} > @@ -432,9 +334,7 @@ export class FilterPanel extends React.Component {
{ this._chosenFacetsCollapse.get(renderInfo.facetHeader) ? - //
{this.sortingCurrentFacetValues(facetHeader)}
&& this._collapseReturnKeys.splice(0) this.sortingCurrentFacetValues(renderInfo.facetHeader) - // && this._collapseReturnKeys.splice(0) : this.displayFacetValueFilterUIs(renderInfo.renderType, renderInfo.facetHeader, renderInfo.domain, renderInfo.range ) } {/* */}
@@ -445,7 +345,6 @@ export class FilterPanel extends React.Component { } private displayFacetValueFilterUIs(type: string | undefined, facetHeader: string, renderInfoDomain?: number[] | undefined, renderInfoRange?: number[] ): React.ReactNode { - // displayFacetValueFilterUIs(renderIinfo) switch (type /* renderInfo.type */ ) { case 'text': // if (this.chosenFacets.get(facetHeader) === 'text') return ( @@ -460,9 +359,7 @@ export class FilterPanel extends React.Component { /> ); case 'checkbox': - return this.facetValues(facetHeader).map(fval => { - const facetValue = fval; return (
@@ -472,12 +369,9 @@ export class FilterPanel extends React.Component { StrListCast(this.targetDoc._childFilters) .find(filter => filter.split(Doc.FilterSep)[0] === facetHeader && filter.split(Doc.FilterSep)[1] == facetValue) ?.split(Doc.FilterSep)[2] === 'check' - } type={type} onChange={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, e.target.checked ? 'check' : 'remove'), 'set filter')} - - /> {facetValue}
@@ -485,48 +379,48 @@ export class FilterPanel extends React.Component { }) case 'range': - console.log("in range") - const domain = renderInfoDomain; - if (domain){ return( - Doc.setDocRangeFilter(this.targetDoc, facetHeader, values)} values={renderInfoRange!} > - {railProps => } - - {({ handles, activeHandleID, getHandleProps }) => ( -
- {handles.map((handle, i) => { - // const value = i === 0 ? defaultValues[0] : defaultValues[1]; - return ( -
- +
+ Doc.setDocRangeFilter(this.targetDoc, facetHeader, values)} values={renderInfoRange!} > + {railProps => } + + {({ handles, activeHandleID, getHandleProps }) => ( +
+ {handles.map((handle, i) => { + // const value = i === 0 ? defaultValues[0] : defaultValues[1]; + return ( +
+ +
+ ); + })} +
+ )} +
+ + {({ tracks, getTrackProps }) => ( +
+ {tracks.map(({ id, source, target }) => ( + + ))}
- ); - })} -
- )} - - - {({ tracks, getTrackProps }) => ( -
- {tracks.map(({ id, source, target }) => ( - - ))} -
- )} -
- - {({ ticks }) => ( -
- {ticks.map(tick => ( - val.toString()} /> - ))} -
- )} -
- + )} + + + {({ ticks }) => ( +
+ {ticks.map(tick => ( + val.toString()} /> + ))} +
+ )} +
+ +
+ ) } diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index d07028ec2..84b1705bc 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1414,14 +1414,19 @@ export namespace Doc { prevLayout === 'icon' && (doc.deiconifyLayout = undefined); doc.layout_fieldKey = deiconify || 'layout'; } - export function setDocRangeFilter(container: Opt, key: string, range?: readonly number[]) { + export function setDocRangeFilter(container: Opt, key: string, range?: readonly number[], modifiers?: 'remove') { //, modifiers: 'remove' | 'set' if (!container) return; - + const childFiltersByRanges = Cast(container._childFiltersByRanges, listSpec('string'), []); + + + + for (let i = 0; i < childFiltersByRanges.length; i += 3) { - console.log("inside if statement") if (childFiltersByRanges[i] === key) { + console.log("this is key inside childfilters by range " + key) childFiltersByRanges.splice(i, 3); + console.log("this is child filters by range " + childFiltersByRanges) break; } } @@ -1431,7 +1436,15 @@ export namespace Doc { childFiltersByRanges.push(range[0].toString()); childFiltersByRanges.push(range[1].toString()); container._childFiltersByRanges = new List(childFiltersByRanges); + console.log("this is child filters by range "+ childFiltersByRanges[0] + "," + childFiltersByRanges[1] + "," + childFiltersByRanges[2]) + console.log("this is new list " + container._childFiltersByRange) + } + + if (modifiers){ + childFiltersByRanges.splice(0,3) + container._childFiltersByRanges = new List(childFiltersByRanges); } + console.log("this is child filters by range END"+ childFiltersByRanges[0] + "," + childFiltersByRanges[1] + "," + childFiltersByRanges[2]) } export const FilterSep = '::'; -- cgit v1.2.3-70-g09d2 From aa9f4b3ced3b4c6a1850cb9a0b3ea2f188998a55 Mon Sep 17 00:00:00 2001 From: eperelm2 Date: Wed, 2 Aug 2023 17:01:35 -0400 Subject: filters - sliders working (still fix UI & comments from meeting) --- src/client/views/FilterPanel.tsx | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 54f5122b4..8ecd60c7e 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -219,21 +219,40 @@ export class FilterPanel extends React.Component { @action sortingCurrentFacetValues = (facetHeader:string) => { - console.log("in function to begin with") + // console.log("in function to begin with") this._collapseReturnKeys.splice(0) - console.log("this si sfacetValies " + this.facetValues(facetHeader)) + // console.log("this si sfacetValies " + this.facetValues(facetHeader)) //if range then display range values + //use to -- & determine amount of sigfinict digits -- make all sections blue evn when collapsed + // transform switch to x and y not x coordinate and y coordinate + + Array.from(this.activeRenderedFacetInfos.keys()).map(renderInfo => { + if ( renderInfo.renderType === "range" && renderInfo.facetHeader === facetHeader) { + console.log("THIS IS ONLY SHWOIGN UP ONCE ") + console.log("hope same thing "+ this.targetDoc?._childFiltersByRanges?.toString + " extra " + renderInfo.range) + this._collapseReturnKeys.push(renderInfo.range) + + } + + }) + + + for (var key of this.facetValues(facetHeader)){ + // console.log("this is key " + key) + if (this.mapActiveFiltersToFacets.get(key)){ + + this._collapseReturnKeys.push(key) + }} + + // if(Array.from(this.activeRenderedFacetInfos.keys()).map(renderInfo => (renderInfo.renderType === "range" && renderInfo.facetHeader === facetHeader ))){ - // console.log("JOE MAMA") + // } - for (var key of this.facetValues(facetHeader)){ - if (this.mapActiveFiltersToFacets.get(key)){ - this._collapseReturnKeys.push(key) - }} + return (
{this._collapseReturnKeys.join(', ') } -- cgit v1.2.3-70-g09d2 From 93854ed0917346720ff519553f909cee3561ec7b Mon Sep 17 00:00:00 2001 From: eperelm2 Date: Thu, 3 Aug 2023 12:31:03 -0400 Subject: filter - fixed bug --- src/client/views/FilterPanel.tsx | 44 +++++++++------------------------------- 1 file changed, 10 insertions(+), 34 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 8ecd60c7e..54701b7f8 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -18,6 +18,9 @@ import { TooltipRail, Handle, Tick, Track } from './nodes/SliderBox-components'; //slight bug when you don't click on background canvas before creating filter and the you click on the canvas + //use to -- & determine amount of sigfinict digits -- make all sections blue evn when collapsed + // transform switch to x and y not x coordinate and y coordinate + interface filterProps { rootDoc: Doc; } @@ -219,40 +222,22 @@ export class FilterPanel extends React.Component { @action sortingCurrentFacetValues = (facetHeader:string) => { - // console.log("in function to begin with") this._collapseReturnKeys.splice(0) - // console.log("this si sfacetValies " + this.facetValues(facetHeader)) - - //if range then display range values - - //use to -- & determine amount of sigfinict digits -- make all sections blue evn when collapsed - // transform switch to x and y not x coordinate and y coordinate - Array.from(this.activeRenderedFacetInfos.keys()).map(renderInfo => { if ( renderInfo.renderType === "range" && renderInfo.facetHeader === facetHeader) { console.log("THIS IS ONLY SHWOIGN UP ONCE ") console.log("hope same thing "+ this.targetDoc?._childFiltersByRanges?.toString + " extra " + renderInfo.range) this._collapseReturnKeys.push(renderInfo.range) - } - + } }) - for (var key of this.facetValues(facetHeader)){ - // console.log("this is key " + key) if (this.mapActiveFiltersToFacets.get(key)){ - this._collapseReturnKeys.push(key) }} - - // if(Array.from(this.activeRenderedFacetInfos.keys()).map(renderInfo => (renderInfo.renderType === "range" && renderInfo.facetHeader === facetHeader ))){ - - // } - - return (
{this._collapseReturnKeys.join(', ') } @@ -315,36 +300,27 @@ export class FilterPanel extends React.Component {
{ - - const collapseBoolValue = this._chosenFacetsCollapse.get(renderInfo.facetHeader) this._chosenFacetsCollapse.set(renderInfo.facetHeader, !collapseBoolValue )})}> - {this._chosenFacetsCollapse.get(renderInfo.facetHeader) ? : }
{ + onClick = {action((e) => { + for (var key of this.facetValues(renderInfo.facetHeader)){ if (this.mapActiveFiltersToFacets.get(key)){ Doc.setDocFilter(this.targetDoc, renderInfo.facetHeader, key, 'remove') }} this._selectedFacetHeaders.delete(renderInfo.facetHeader) this._chosenFacetsCollapse.delete(renderInfo.facetHeader) - Doc.setDocRangeFilter(this.targetDoc, renderInfo.facetHeader, renderInfo.domain, 'remove') - - - - console.log("this is activeFilters " + this.activeFilters) - console.log("this is activeFacetHeaders " + this.activeFacetHeaders) - console.log("thsi is activeRenderedFacetInfos " + this.activeRenderedFacetInfos) - console.log("thsi is selected facet Headers " + this._selectedFacetHeaders ) - console.log("THIS IS THE ONE ADDED "+ this.targetDoc?._childFiltersByRanges) - - + if (renderInfo.domain){ + Doc.setDocRangeFilter(this.targetDoc, renderInfo.facetHeader, renderInfo.domain, 'remove') + } + })} >
-- cgit v1.2.3-70-g09d2 From 082a280ed989007d84c8619438889c64a6fedb14 Mon Sep 17 00:00:00 2001 From: eperelm2 Date: Fri, 4 Aug 2023 11:54:03 -0400 Subject: filters - starting to add filterable field --- src/client/documents/Documents.ts | 6 +++--- src/client/views/FilterPanel.tsx | 9 +-------- src/client/views/MainView.scss | 8 ++++---- src/client/views/MainView.tsx | 2 +- 4 files changed, 9 insertions(+), 16 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 5d7ca6f6d..5d8ae19fc 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -88,7 +88,7 @@ class BoolInfo extends FInfo { class NumInfo extends FInfo { fieldType? = 'number'; values?: number[] = []; - constructor(d: string, readOnly?: boolean, values?: number[]) { + constructor(d: string, readOnly?: boolean, values?: number[], filterable?:boolean) { super(d, readOnly); this.values = values; } @@ -104,7 +104,7 @@ class StrInfo extends FInfo { class DocInfo extends FInfo { fieldType? = 'Doc'; values?: Doc[] = []; - constructor(d: string, values?: Doc[]) { + constructor(d: string, filterable?:boolean, values?: Doc[] ) { super(d, true); this.values = values; } @@ -183,7 +183,7 @@ export class DocumentOptions { caption?: RichTextField; author?: string; // STRt = new StrInfo('creator of document'); // bcz: don't change this. Otherwise, the userDoc's field Infos will have a FieldInfo assigned to its author field which will render it unreadable author_date?: DATEt = new DateInfo('date the document was created', true); - annotationOn?: DOCt = new DocInfo('document annotated by this document'); + annotationOn?: DOCt = new DocInfo('document annotated by this document', false); color?: STRt = new StrInfo('foreground color data doc'); hidden?: BOOLt = new BoolInfo('whether the document is not rendered by its collection'); backgroundColor?: STRt = new StrInfo('background color for data doc'); diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 54701b7f8..127708ca3 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -226,8 +226,6 @@ export class FilterPanel extends React.Component { Array.from(this.activeRenderedFacetInfos.keys()).map(renderInfo => { if ( renderInfo.renderType === "range" && renderInfo.facetHeader === facetHeader) { - console.log("THIS IS ONLY SHWOIGN UP ONCE ") - console.log("hope same thing "+ this.targetDoc?._childFiltersByRanges?.toString + " extra " + renderInfo.range) this._collapseReturnKeys.push(renderInfo.range) } @@ -316,16 +314,11 @@ export class FilterPanel extends React.Component { this._selectedFacetHeaders.delete(renderInfo.facetHeader) this._chosenFacetsCollapse.delete(renderInfo.facetHeader) - if (renderInfo.domain){ Doc.setDocRangeFilter(this.targetDoc, renderInfo.facetHeader, renderInfo.domain, 'remove') - } - - })} > + }})} >
- {/*
*/} -
{ this._chosenFacetsCollapse.get(renderInfo.facetHeader) ? diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss index b3faff442..8a7f5132b 100644 --- a/src/client/views/MainView.scss +++ b/src/client/views/MainView.scss @@ -194,11 +194,11 @@ h1, left: 0; position: absolute; z-index: 2; - background-color: linen; //$light-gray; + // background-color: linen; //$light-gray; - .editable-title { - background-color: linen; //$light-gray; - } + // .editable-title { + // background-color: linen; //$light-gray; + // } } } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index cbaa763f5..d9136dbd4 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -813,7 +813,7 @@ export class MainView extends React.Component { {this.dockingContent} {this._hideUI ? null : ( -
+
)} -- cgit v1.2.3-70-g09d2 From 4c8eee9811abd072d2a6adfe24eaf04f980ccf21 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 9 Aug 2023 15:21:20 -0400 Subject: updated file system to include recentlyClosed, Shared, and Dashboards and fixed drag drop to make sense for the filesystem. Fixed loading documents to happen in one batch by fixing UPDATE_CACHED_DOCS to save only documents accessible from current dashboard. --- src/Utils.ts | 2 +- src/client/DocServer.ts | 60 +- src/client/documents/DocumentTypes.ts | 4 - src/client/documents/Documents.ts | 12 +- src/client/util/CurrentUserUtils.ts | 37 +- src/client/util/DocumentManager.ts | 5 +- src/client/util/DragManager.ts | 4 +- src/client/util/GroupManager.tsx | 5 +- src/client/util/GroupMemberView.tsx | 3 +- src/client/util/LinkManager.ts | 4 +- src/client/util/ReplayMovements.ts | 1 - src/client/util/ServerStats.tsx | 26 +- src/client/util/SettingsManager.tsx | 11 +- src/client/util/SharingManager.tsx | 11 +- src/client/util/reportManager/ReportManager.tsx | 5 +- src/client/views/DashboardView.tsx | 83 +-- src/client/views/DocComponent.tsx | 4 +- src/client/views/FilterPanel.tsx | 18 +- src/client/views/LightboxView.tsx | 4 +- src/client/views/Main.tsx | 5 +- src/client/views/MainView.tsx | 12 +- src/client/views/PropertiesButtons.tsx | 1 - src/client/views/PropertiesDocContextSelector.tsx | 1 - src/client/views/PropertiesSection.tsx | 80 ++- src/client/views/PropertiesView.tsx | 758 ++++++++++----------- src/client/views/StyleProvider.tsx | 8 +- src/client/views/UndoStack.tsx | 43 +- .../views/collections/CollectionDockingView.tsx | 7 +- src/client/views/collections/CollectionMenu.tsx | 2 +- .../views/collections/CollectionStackingView.tsx | 1 - .../views/collections/CollectionTreeView.tsx | 1 + src/client/views/collections/TabDocView.tsx | 2 +- src/client/views/collections/TreeView.tsx | 2 +- .../collections/collectionFreeForm/MarqueeView.tsx | 1 - src/client/views/global/globalScripts.ts | 1 - .../views/newlightbox/ExploreView/ExploreView.tsx | 3 - .../components/Recommendation/Recommendation.tsx | 1 - src/client/views/nodes/DataVizBox/utils/D3Utils.ts | 1 - src/client/views/nodes/DocumentView.tsx | 3 +- src/client/views/nodes/LinkDocPreview.tsx | 2 +- src/client/views/nodes/MapBox/MapBox.tsx | 1 - src/client/views/nodes/ScreenshotBox.tsx | 5 +- src/client/views/nodes/ScriptingBox.tsx | 2 - .../views/nodes/formattedText/FormattedTextBox.tsx | 20 +- .../views/nodes/formattedText/RichTextRules.ts | 26 +- src/client/views/pdf/AnchorMenu.tsx | 5 +- src/client/views/search/SearchBox.tsx | 78 ++- src/client/views/topbar/TopBar.tsx | 38 +- src/fields/Doc.ts | 81 ++- src/fields/FieldLoader.tsx | 5 +- src/server/DashUploadUtils.ts | 3 +- 51 files changed, 727 insertions(+), 771 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/Utils.ts b/src/Utils.ts index 8b9fe2aab..7f83ab8f5 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -76,7 +76,7 @@ export namespace Utils { }); return returnedUri; } catch (e) { - console.log('VideoBox :' + e); + console.log('ConvertDataURI :' + e); } } diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index ad5a73598..40979d631 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -1,16 +1,18 @@ import { runInAction } from 'mobx'; import * as rp from 'request-promise'; import * as io from 'socket.io-client'; -import { Doc, Opt } from '../fields/Doc'; +import { Doc, DocListCast, Opt } from '../fields/Doc'; import { UpdatingFromServer } from '../fields/DocSymbols'; import { FieldLoader } from '../fields/FieldLoader'; import { HandleUpdate, Id, Parent } from '../fields/FieldSymbols'; import { ObjectField } from '../fields/ObjectField'; import { RefField } from '../fields/RefField'; -import { StrCast } from '../fields/Types'; +import { DocCast, StrCast } from '../fields/Types'; import MobileInkOverlay from '../mobile/MobileInkOverlay'; import { emptyFunction, Utils } from '../Utils'; import { GestureContent, MessageStore, MobileDocumentUploadContent, MobileInkOverlayContent, UpdateMobileInkOverlayPositionContent, YoutubeQueryTypes } from './../server/Message'; +import { DocumentType } from './documents/DocumentTypes'; +import { LinkManager } from './util/LinkManager'; import { SerializationHelper } from './util/SerializationHelper'; import { GestureOverlay } from './views/GestureOverlay'; @@ -30,35 +32,44 @@ import { GestureOverlay } from './views/GestureOverlay'; export namespace DocServer { let _cache: { [id: string]: RefField | Promise> } = {}; - export function QUERY_SERVER_CACHE(title: string) { + export function FindDocByTitle(title: string) { const foundDocId = Array.from(Object.keys(_cache)) .filter(key => _cache[key] instanceof Doc) .find(key => (_cache[key] as Doc).title === title); return foundDocId ? (_cache[foundDocId] as Doc) : undefined; } - let lastCacheUpdate = 0; - export function UPDATE_SERVER_CACHE(print: boolean = false) { - if (print) { - const strings: string[] = []; - Array.from(Object.keys(_cache)).forEach(key => { - const doc = _cache[key]; - if (doc instanceof Doc) strings.push(StrCast(doc.author) + ' ' + StrCast(doc.title) + ' ' + StrCast(Doc.GetT(doc, 'title', 'string', true))); - }); - strings.sort().forEach((str, i) => console.log(i.toString() + ' ' + str)); - } - const filtered = Array.from(Object.keys(_cache)).filter(key => { - const doc = _cache[key] as Doc; - return true; - if (!(StrCast(doc.author).includes('.edu') || StrCast(doc.author).includes('.com')) || doc.author === Doc.CurrentUserEmail) return true; - return false; + let cacheDocumentIds = ''; // ; separate string of all documents ids in the user's working set (cached on the server) + export let CacheNeedsUpdate = false; + export function UPDATE_SERVER_CACHE() { + const prototypes = Object.values(DocumentType) + .filter(type => type !== DocumentType.NONE) + .map(type => _cache[type + 'Proto']) + .filter(doc => doc instanceof Doc) + .map(doc => doc as Doc); + const references = new Set(prototypes); + Doc.FindReferences(Doc.UserDoc(), references, undefined); + DocListCast(DocCast(Doc.UserDoc().myLinkDatabase).data).forEach(link => { + if (!references.has(DocCast(link.link_anchor_1)) && !references.has(DocCast(link.link_anchor_2))) { + Doc.RemoveDocFromList(DocCast(Doc.UserDoc().myLinkDatabase), 'data', link); + } }); - if (filtered.length === lastCacheUpdate) return; - lastCacheUpdate = filtered.length; + LinkManager.userLinkDBs.forEach(linkDb => Doc.FindReferences(linkDb, references, undefined)); + const filtered = Array.from(references); + + const newCacheUpdate = filtered.map(doc => doc[Id]).join(';'); + if (newCacheUpdate === cacheDocumentIds) return; + cacheDocumentIds = newCacheUpdate; + + // print out cached docs + console.log('Set cached docs = '); + const is_filtered = filtered.filter(doc => !Doc.IsSystem(doc)); + const strings = is_filtered.map(doc => StrCast(doc.title) + ' ' + (Doc.IsDataProto(doc) ? '(data)' : '(embedding)')); + strings.sort().forEach((str, i) => console.log(i.toString() + ' ' + str)); rp.post(Utils.prepend('/setCacheDocumentIds'), { body: { - cacheDocumentIds: filtered.join(';'), + cacheDocumentIds, }, json: true, }); @@ -353,7 +364,7 @@ export namespace DocServer { // i) which documents need to be fetched // ii) which are already in the process of being fetched // iii) which already exist in the cache - for (const id of ids) { + for (const id of ids.filter(id => id)) { const cached = _cache[id]; if (cached === undefined) { defaultPromises.push({ @@ -382,7 +393,7 @@ export namespace DocServer { // 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 console.log('Requesting ' + requestedIds.length); - FieldLoader.active && runInAction(() => (FieldLoader.ServerLoadStatus.requested = requestedIds.length)); + setTimeout(() => runInAction(() => (FieldLoader.ServerLoadStatus.requested = requestedIds.length))); const serializedFields = await Utils.EmitCallback(_socket, MessageStore.GetRefFields, requestedIds); // 3) when the serialized RefFields have been received, go head and begin deserializing them into objects. @@ -392,7 +403,7 @@ export namespace DocServer { console.log('deserializing ' + serializedFields.length + ' fields'); for (const field of serializedFields) { processed++; - if (FieldLoader.active && processed % 150 === 0) { + if (processed % 150 === 0) { runInAction(() => (FieldLoader.ServerLoadStatus.retrieved = processed)); await new Promise(res => setTimeout(res)); // force loading to yield to splash screen rendering to update progress } @@ -478,6 +489,7 @@ export namespace DocServer { * @param field the [RefField] to be serialized and sent to the server to be stored in the database */ export function CreateField(field: RefField) { + CacheNeedsUpdate = true; _CreateField(field); } diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index b629d9b8c..1d0ddce40 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -14,13 +14,11 @@ export enum DocumentType { INK = 'ink', SCREENSHOT = 'screenshot', FONTICON = 'fonticonbox', - FILTER = 'filter', SEARCH = 'search', // search query LABEL = 'label', // simple text label BUTTON = 'button', // onClick button WEBCAM = 'webcam', // webcam CONFIG = 'config', // configuration document intended to specify a view layout configuration, but not be directly rendered (e.g., for saving the page# of a PDF, or view transform of a collection) - DATE = 'date', // calendar view of a date SCRIPTING = 'script', // script editor EQUATION = 'equation', // equation editor FUNCPLOT = 'funcplot', // function plotter @@ -31,14 +29,12 @@ export enum DocumentType { // special purpose wrappers that either take no data or are compositions of lower level types LINK = 'link', - LINKANCHOR = 'linkanchor', IMPORT = 'import', SLIDER = 'slider', PRES = 'presentation', PRESELEMENT = 'preselement', COLOR = 'color', YOUTUBE = 'youtube', - SEARCHITEM = 'searchitem', COMPARISON = 'comparison', GROUP = 'group', diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 8eeceaa15..fccad80ee 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1,5 +1,5 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; -import { action, runInAction } from 'mobx'; +import { action, reaction, runInAction } from 'mobx'; import { basename } from 'path'; import { DateField } from '../../fields/DateField'; import { Doc, DocListCast, Field, Opt, updateCachedAcls } from '../../fields/Doc'; @@ -744,6 +744,10 @@ export namespace Docs { // an entry dedicated to the given DocumentType) target && PrototypeMap.set(type, target); }); + reaction( + () => (proto => StrCast(proto?.BROADCAST_MESSAGE))(DocServer.GetCachedRefField('rtfProto') as Doc), + msg => msg && alert(msg) + ); } /** @@ -887,8 +891,6 @@ export namespace Docs { DocUtils.MakeLinkToActiveAudio(() => viewDoc); } - Doc.AddFileOrphan(dataDoc); - updateCachedAcls(dataDoc); updateCachedAcls(viewDoc); @@ -1150,9 +1152,6 @@ export namespace Docs { export function FontIconDocument(options?: DocumentOptions) { return InstanceFromProto(Prototypes.get(DocumentType.FONTICON), undefined, { ...(options || {}) }); } - export function FilterDocument(options?: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.FILTER), undefined, { ...(options || {}) }); - } export function PresElementBoxDocument() { return Prototypes.get(DocumentType.PRESELEMENT); @@ -1872,7 +1871,6 @@ export namespace DocUtils { export function copyDragFactory(dragFactory: Doc) { if (!dragFactory) return undefined; const ndoc = dragFactory.isTemplateDoc ? Doc.ApplyTemplate(dragFactory) : Doc.MakeCopy(dragFactory, true); - ndoc && Doc.AddFileOrphan(Doc.GetProto(ndoc)); if (ndoc && dragFactory['dragFactory_count'] !== undefined) { dragFactory['dragFactory_count'] = NumCast(dragFactory['dragFactory_count']) + 1; Doc.SetInPlace(ndoc, 'title', ndoc.title + ' ' + NumCast(dragFactory['dragFactory_count']).toString(), true); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 21bcec6d1..e8262ff3b 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -152,7 +152,7 @@ export class CurrentUserUtils { { noteType: "Idea", backgroundColor: "pink", icon: "lightbulb" }, { noteType: "Topic", backgroundColor: "lightblue", icon: "book-open" }]; const reqdNoteList = reqdTempOpts.map(opts => { - const reqdOpts = {...opts, title: "text", width:200, layout_autoHeight: true, layout_fitWidth: true}; + const reqdOpts = {...opts, isSystem:true, title: "text", width:200, layout_autoHeight: true, layout_fitWidth: true}; const noteType = tempNotes ? DocListCast(tempNotes.data).find(doc => doc.noteType === opts.noteType): undefined; return DocUtils.AssignOpts(noteType, reqdOpts) ?? MakeTemplate(Docs.Create.TextDocument("",reqdOpts), true, opts.noteType??"Note"); }); @@ -339,7 +339,7 @@ export class CurrentUserUtils { } /// returns descriptions needed to buttons for the left sidebar to open up panes displaying different collections of documents - static leftSidebarMenuBtnDescriptions(doc: Doc):{title:string, target:Doc, icon:string, toolTip: string, scripts:{[key:string]:any}, funcs?:{[key:string]:any}}[] { + static leftSidebarMenuBtnDescriptions(doc: Doc):{title:string, target:Doc, icon:string, toolTip: string, scripts:{[key:string]:any}, funcs?:{[key:string]:any}, hidden?: boolean}[] { const badgeValue = "((len) => len && len !== '0' ? len: undefined)(docList(self.target.data).filter(doc => !docList(self.target.viewed).includes(doc)).length.toString())"; const getActiveDashTrails = "Doc.ActiveDashboard?.myTrails"; return [ @@ -348,7 +348,7 @@ export class CurrentUserUtils { { title: "Files", toolTip: "Files", target: this.setupFilesystem(doc, "myFilesystem"), ignoreClick: true, icon: "folder-open", }, { title: "Tools", toolTip: "Tools", target: this.setupToolsBtnPanel(doc, "myTools"), ignoreClick: true, icon: "wrench", funcs: {hidden: "IsNoviceMode()"} }, { title: "Imports", toolTip: "Imports ⌘I", target: this.setupImportSidebar(doc, "myImports"), ignoreClick:false, icon: "upload", }, - { title: "Closed", toolTip: "Recently Closed", target: this.setupRecentlyClosed(doc, "myRecentlyClosed"), ignoreClick: true, icon: "archive", }, + { title: "Closed", toolTip: "Recently Closed", target: this.setupRecentlyClosed(doc, "myRecentlyClosed"), ignoreClick: true, icon: "archive", hidden: true }, // this doc is hidden from the Sidebar, but it's still being used in MyFilesystem which ignores the hidden field { title: "Shared", toolTip: "Shared Docs", target: Doc.MySharedDocs, ignoreClick: true, icon: "users", funcs: {badgeValue: badgeValue}}, { title: "Trails", toolTip: "Trails ⌘R", target: Doc.UserDoc(), ignoreClick: true, icon: "pres-trail", funcs: {target: getActiveDashTrails}}, { title: "User Doc", toolTip: "User Doc", target: this.setupUserDocView(doc, "myUserDocView"), ignoreClick: true, icon: "address-card",funcs: {hidden: "IsNoviceMode()"} }, @@ -357,17 +357,17 @@ export class CurrentUserUtils { /// the empty panel that is filled with whichever left menu button's panel has been selected static setupLeftSidebarPanel(doc: Doc, field="myLeftSidebarPanel") { - DocUtils.AssignDocField(doc, field, (opts) => Doc.assign(new Doc(), opts as any), {isSystem:true, undoIgnoreFields: new List(['proto'])}); + DocUtils.AssignDocField(doc, field, (opts) => Doc.assign(new Doc(), opts as any), {title:"leftSidebarPanel", isSystem:true, undoIgnoreFields: new List(['proto'])}); } /// Initializes the left sidebar menu buttons and the panels they open up static setupLeftSidebarMenu(doc: Doc, field="myLeftSidebarMenu") { this.setupLeftSidebarPanel(doc); const myLeftSidebarMenu = DocCast(doc[field]); - const menuBtns = CurrentUserUtils.leftSidebarMenuBtnDescriptions(doc).map(({ title, target, icon, toolTip, scripts, funcs }) => { + const menuBtns = CurrentUserUtils.leftSidebarMenuBtnDescriptions(doc).map(({ title, target, icon, toolTip, hidden, scripts, funcs }) => { const btnDoc = myLeftSidebarMenu ? DocListCast(myLeftSidebarMenu.data).find(doc => doc.title === title) : undefined; const reqdBtnOpts:DocumentOptions = { - title, icon, target, toolTip, btnType: ButtonType.MenuButton, isSystem: true, undoIgnoreFields: new List(['height', 'data_columnHeaders']), dontRegisterView: true, + title, icon, target, toolTip, hidden, btnType: ButtonType.MenuButton, isSystem: true, undoIgnoreFields: new List(['height', 'data_columnHeaders']), dontRegisterView: true, _width: 60, _height: 60, _dragOnlyWithinContainer: true, _layout_hideContextMenu: true, }; return DocUtils.AssignScripts(DocUtils.AssignOpts(btnDoc, reqdBtnOpts) ?? Docs.Create.FontIconDocument(reqdBtnOpts), scripts, funcs); @@ -495,7 +495,7 @@ export class CurrentUserUtils { const reqdOpts:DocumentOptions = { title: "My Dashboards", childHideLinkButton: true, treeViewFreezeChildren: "remove|add", treeViewHideTitle: true, layout_boxShadow: "0 0", childDontRegisterViews: true, dropAction: "same", treeViewType: TreeViewType.fileSystem, isFolder: true, isSystem: true, treeViewTruncateTitleWidth: 350, ignoreClick: true, - layout_headerButton: newDashboardButton, childDragAction: "embed", + layout_headerButton: newDashboardButton, childDragAction: "none", _layout_showTitle: "title", _height: 400, _gridGap: 5, _forceActive: true, _lockedPosition: true, contextMenuLabels:new List(contextMenuLabels), contextMenuIcons:new List(contextMenuIcons), @@ -519,7 +519,6 @@ export class CurrentUserUtils { /// initializes the left sidebar File system pane static setupFilesystem(doc: Doc, field:string) { var myFilesystem = DocCast(doc[field]); - const myFileOrphans = DocUtils.AssignDocField(doc, "myFileOrphans", (opts) => Docs.Create.TreeDocument([], opts), { title: "Unfiled", undoIgnoreFields:new List(['treeViewSortCriterion']), _dragOnlyWithinContainer: true, isSystem: true, isFolder: true }); const newFolder = `TreeView_addNewFolder()`; const newFolderOpts: DocumentOptions = { @@ -530,14 +529,15 @@ export class CurrentUserUtils { const newFolderButton = DocUtils.AssignScripts(DocUtils.AssignOpts(DocCast(myFilesystem?.layout_headerButton), newFolderOpts) ?? Docs.Create.FontIconDocument(newFolderOpts), newFolderScript); const reqdOpts:DocumentOptions = { _layout_showTitle: "title", _height: 100, _gridGap: 5, _forceActive: true, _lockedPosition: true, - title: "My Documents", layout_headerButton: newFolderButton, treeViewHideTitle: true, dropAction: "proto", isSystem: true, + title: "My Documents", layout_headerButton: newFolderButton, treeViewHideTitle: true, dropAction: 'add', isSystem: true, isFolder: true, treeViewType: TreeViewType.fileSystem, childHideLinkButton: true, layout_boxShadow: "0 0", childDontRegisterViews: true, treeViewTruncateTitleWidth: 350, ignoreClick: true, childDragAction: "embed", childContextMenuLabels: new List(["Create new folder"]), childContextMenuIcons: new List(["plus"]), layout_explainer: "This is your file manager where you can create folders to keep track of documents independently of your dashboard." }; - myFilesystem = DocUtils.AssignDocField(doc, field, (opts, items) => Docs.Create.TreeDocument(items??[], opts), reqdOpts, [myFileOrphans]); + const fileFolders = new Set(DocListCast(DocCast(doc[field])?.data)); + myFilesystem = DocUtils.AssignDocField(doc, field, (opts, items) => Docs.Create.TreeDocument(items??[], opts), reqdOpts, Array.from(fileFolders)); const childContextMenuScripts = [newFolder]; if (Cast(myFilesystem.childContextMenuScripts, listSpec(ScriptField), null)?.length !== childContextMenuScripts.length) { myFilesystem.childContextMenuScripts = new List(childContextMenuScripts.map(script => ScriptField.MakeFunction(script)!)); @@ -547,8 +547,8 @@ export class CurrentUserUtils { /// initializes the panel displaying docs that have been recently closed static setupRecentlyClosed(doc: Doc, field:string) { - const reqdOpts:DocumentOptions = { _layout_showTitle: "title", _lockedPosition: true, _gridGap: 5, _forceActive: true, - title: "My Recently Closed", childHideLinkButton: true, treeViewHideTitle: true, childDragAction: "embed", isSystem: true, + const reqdOpts:DocumentOptions = { _layout_showTitle: "title", _lockedPosition: true, _gridGap: 5, _forceActive: true, isFolder: true, + title: "My Recently Closed", childHideLinkButton: true, treeViewHideTitle: true, childDragAction: "move", isSystem: true, treeViewTruncateTitleWidth: 350, ignoreClick: true, layout_boxShadow: "0 0", childDontRegisterViews: true, dropAction: "same", contextMenuLabels: new List(["Empty recently closed"]), contextMenuIcons:new List(["trash"]), @@ -562,8 +562,6 @@ export class CurrentUserUtils { toolTip: "Empty recently closed",}; DocUtils.AssignDocField(recentlyClosed, "layout_headerButton", (opts) => Docs.Create.FontIconDocument(opts), clearBtnsOpts, undefined, {onClick: clearAll("self.target")}); - //if (recentlyClosed.layout_headerButton !== clearDocsButton) Doc.GetProto(recentlyClosed).layout_headerButton = clearDocsButton; - if (!Cast(recentlyClosed.contextMenuScripts, listSpec(ScriptField),null)?.find((script) => script.script.originalScript === clearAll("self"))) { recentlyClosed.contextMenuScripts = new List([ScriptField.MakeScript(clearAll("self"))!]) } @@ -777,6 +775,7 @@ export class CurrentUserUtils { const linkDocs = new Doc(linkDatabaseId, true); linkDocs.title = "LINK DATABASE: " + Doc.CurrentUserEmail; linkDocs.author = Doc.CurrentUserEmail; + linkDocs.isSystem = true; linkDocs.data = new List([]); linkDocs["acl-Guest"] = SharingPermissions.Augment; doc.myLinkDatabase = new PrefetchProxy(linkDocs); @@ -877,11 +876,13 @@ export class CurrentUserUtils { this.setupDockedButtons(doc); // the bottom bar of font icons this.setupLeftSidebarMenu(doc); // the left-side column of buttons that open their contents in a flyout panel on the left this.setupDocTemplates(doc); // sets up the template menu of templates - this.setupFieldInfos(doc); // sets up the collection of field info descriptions for each possible DocumentOption + //this.setupFieldInfos(doc); // sets up the collection of field info descriptions for each possible DocumentOption DocUtils.AssignDocField(doc, "globalScriptDatabase", (opts) => Docs.Prototypes.MainScriptDocument(), {}); - DocUtils.AssignDocField(doc, "myHeaderBar", (opts) => Docs.Create.MulticolumnDocument([], opts), { title: "header bar", isSystem: true, childDocumentsActive:false, dropAction: 'move'}); // drop down panel at top of dashboard for stashing documents + DocUtils.AssignDocField(doc, "myHeaderBar", (opts) => Docs.Create.MulticolumnDocument([], opts), { title: "My Header Bar", isSystem: true, childDocumentsActive:false, dropAction: 'move'}); // drop down panel at top of dashboard for stashing documents + Doc.AddDocToList(Doc.MyFilesystem, undefined, Doc.MyDashboards) Doc.AddDocToList(Doc.MyFilesystem, undefined, Doc.MySharedDocs) + Doc.AddDocToList(Doc.MyFilesystem, undefined, Doc.MyRecentlyClosed) if (doc.activeDashboard instanceof Doc) { // undefined means ColorScheme.Light until all CSS is updated with values for each color scheme (e.g., see MainView.scss, DocumentDecorations.scss) @@ -889,7 +890,7 @@ export class CurrentUserUtils { } new LinkManager(); - setTimeout(DocServer.UPDATE_SERVER_CACHE, 2500); + DocServer.CacheNeedsUpdate && setTimeout(DocServer.UPDATE_SERVER_CACHE, 2500); setInterval(DocServer.UPDATE_SERVER_CACHE, 120000); return doc; } @@ -923,11 +924,9 @@ export class CurrentUserUtils { { const ids = result.cacheDocumentIds.split(";"); const batch = 30000; - FieldLoader.active = true; for (let i = 0; i < ids.length; i = Math.min(ids.length, i+batch)) { await DocServer.GetRefFields(ids.slice(i, i+batch)); } - FieldLoader.active = false; } return result; } else { diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 8e4e0d8f3..42132c2d7 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -75,7 +75,7 @@ export class DocumentManager { @action public AddView = (view: DocumentView) => { - //console.log("MOUNT " + view.props.Document.title + "/" + view.props.LayoutTemplateString); + if (view.props.LayoutTemplateString?.includes(KeyValueBox.name)) return; if (view.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) { const viewAnchorIndex = view.props.LayoutTemplateString.includes('link_anchor_2') ? 'link_anchor_2' : 'link_anchor_1'; const link = view.rootDoc; @@ -251,6 +251,7 @@ export class DocumentManager { options: DocFocusOptions, // options for how to navigate to target finished?: (changed: boolean) => void // func called after focusing on target with flag indicating whether anything needed to be done. ) => { + Doc.RemoveDocFromList(Doc.MyRecentlyClosed, undefined, targetDoc); const docContextPath = DocumentManager.GetContextPath(targetDoc, true); if (docContextPath.some(doc => doc.hidden)) options.toggleTarget = false; let rootContextView = @@ -335,7 +336,7 @@ export function DocFocusOrOpen(doc: Doc, options: DocFocusOptions = { willZoomCe if (dv && (!containingDoc || dv.props.docViewPath().lastElement()?.Document === containingDoc)) { DocumentManager.Instance.showDocumentView(dv, options).then(() => dv && Doc.linkFollowHighlight(dv.rootDoc)); } else { - const container = DocCast(containingDoc ?? doc.embedContainer ?? doc); + const container = DocCast(containingDoc ?? doc.embedContainer ?? Doc.BestEmbedding(doc)); const showDoc = !Doc.IsSystem(container) ? container : doc; options.toggleTarget = undefined; DocumentManager.Instance.showDocument(showDoc, options, () => DocumentManager.Instance.showDocument(doc, { ...options, openLocation: undefined })).then(() => { diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 85101fcab..f4ff38515 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -15,7 +15,7 @@ import { SelectionManager } from './SelectionManager'; import { SnappingManager } from './SnappingManager'; import { UndoManager } from './UndoManager'; -export type dropActionType = 'embed' | 'copy' | 'move' | 'same' | 'proto' | 'none' | undefined; // undefined = move, "same" = move but don't call dropPropertiesToRemove +export type dropActionType = 'embed' | 'copy' | 'move' | 'add' | 'same' | 'proto' | 'none' | undefined; // undefined = move, "same" = move but don't call dropPropertiesToRemove /** * Initialize drag @@ -213,6 +213,8 @@ export namespace DragManager { ? addAudioTag(ScriptCast(d.onDragStart).script.run({ this: d }).result) : docDragData.dropAction === 'embed' ? Doc.BestEmbedding(d) + : docDragData.dropAction === 'add' + ? d : docDragData.dropAction === 'proto' ? Doc.GetProto(d) : docDragData.dropAction === 'copy' diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx index e406d89e7..f35844020 100644 --- a/src/client/util/GroupManager.tsx +++ b/src/client/util/GroupManager.tsx @@ -16,6 +16,7 @@ import { listSpec } from '../../fields/Schema'; import { DateField } from '../../fields/DateField'; import { Id } from '../../fields/FieldSymbols'; import { Button, IconButton, Size, Type } from 'browndash-components'; +import { SettingsManager } from './SettingsManager'; /** * Interface for options for the react-select component @@ -281,7 +282,7 @@ export class GroupManager extends React.Component<{}> { */ private get groupCreationModal() { const contents = ( -
+

New Group @@ -366,7 +367,7 @@ export class GroupManager extends React.Component<{}> { const groups = this.groupSort === 'ascending' ? this.allGroups.sort(sortGroups) : this.groupSort === 'descending' ? this.allGroups.sort(sortGroups).reverse() : this.allGroups; return ( -

+
{this.groupCreationModal} {this.currentGroup ? (this.currentGroup = undefined))} /> : null}
diff --git a/src/client/util/GroupMemberView.tsx b/src/client/util/GroupMemberView.tsx index 057f94f64..535d8ccc2 100644 --- a/src/client/util/GroupMemberView.tsx +++ b/src/client/util/GroupMemberView.tsx @@ -9,6 +9,7 @@ import { MainViewModal } from '../views/MainViewModal'; import { GroupManager, UserOptions } from './GroupManager'; import './GroupMemberView.scss'; import { Button, IconButton, Size, Type } from 'browndash-components'; +import { SettingsManager } from './SettingsManager'; interface GroupMemberViewProps { group: Doc; @@ -28,7 +29,7 @@ export class GroupMemberView extends React.Component { const hasEditAccess = GroupManager.Instance.hasEditAccess(this.props.group); return !this.props.group ? null : ( -
+
(FieldLoader.ServerLoadStatus.message = 'links')); LinkManager.addLinkDB(Doc.LinkDBDoc()); } diff --git a/src/client/util/ReplayMovements.ts b/src/client/util/ReplayMovements.ts index cbc465d6a..d99630f82 100644 --- a/src/client/util/ReplayMovements.ts +++ b/src/client/util/ReplayMovements.ts @@ -187,7 +187,6 @@ export class ReplayMovements { } else { // tab wasn't open - open it and play the movement const openedColFFView = this.openTab(movement.doc); - console.log('openedColFFView', openedColFFView); openedColFFView && this.zoomAndPan(movement, openedColFFView); } diff --git a/src/client/util/ServerStats.tsx b/src/client/util/ServerStats.tsx index 6a6ec158e..3c7c35a7e 100644 --- a/src/client/util/ServerStats.tsx +++ b/src/client/util/ServerStats.tsx @@ -6,6 +6,7 @@ import './SharingManager.scss'; import { PingManager } from './PingManager'; import { StrCast } from '../../fields/Types'; import { Doc } from '../../fields/Doc'; +import { SettingsManager } from './SettingsManager'; @observer export class ServerStats extends React.Component<{}> { @@ -42,21 +43,22 @@ export class ServerStats extends React.Component<{}> { */ @computed get sharingInterface() { return ( -
-
- {PingManager.Instance.IsBeating ? 'The server connection is active' : - 'The server connection has been interrupted.NOTE: Any changes made will appear to persist but will be lost after a browser refreshes.'} - -
+
+
+ {PingManager.Instance.IsBeating ? 'The server connection is active' : 'The server connection has been interrupted.NOTE: Any changes made will appear to persist but will be lost after a browser refreshes.'} + +
Active users:{this._stats?.socketMap.length} {this._stats?.socketMap.map((user: any) => (

{user.username}

- ))} + ))}
); diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index b8e327968..573900825 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -1,10 +1,11 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Button, ColorPicker, Dropdown, DropdownType, EditableText, Group, NumberDropdown, Size, Toggle, ToggleType, Type } from 'browndash-components'; import { action, computed, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { ColorState, SketchPicker } from 'react-color'; +import { BsGoogle } from 'react-icons/bs'; +import { FaFillDrip, FaPalette } from 'react-icons/fa'; import { Doc } from '../../fields/Doc'; -import { Id } from '../../fields/FieldSymbols'; import { BoolCast, Cast, StrCast } from '../../fields/Types'; import { addStyleSheet, addStyleSheetRule, Utils } from '../../Utils'; import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager'; @@ -12,13 +13,9 @@ import { DocServer } from '../DocServer'; import { Networking } from '../Network'; import { MainViewModal } from '../views/MainViewModal'; import { FontIconBox } from '../views/nodes/FontIconBox/FontIconBox'; -import { DragManager } from './DragManager'; import { GroupManager } from './GroupManager'; import './SettingsManager.scss'; import { undoBatch } from './UndoManager'; -import { Button, ColorPicker, Dropdown, DropdownType, EditableText, Group, NumberDropdown, Size, Toggle, ToggleType, Type } from 'browndash-components'; -import { BsGoogle } from 'react-icons/bs'; -import { FaFillDrip, FaPalette } from 'react-icons/fa'; const higflyout = require('@hig/flyout'); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -39,6 +36,7 @@ export enum freeformScrollMode { @observer export class SettingsManager extends React.Component<{}> { + static Version = 'v0.5'; public static Instance: SettingsManager; static _settingsStyle = addStyleSheet(); @observable public isOpen = false; @@ -452,6 +450,7 @@ export class SettingsManager extends React.Component<{}> {
+
{SettingsManager.Version}
{Doc.CurrentUserEmail}
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index cadcb1f8a..6171c01d7 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -8,6 +8,7 @@ import Select from 'react-select'; import * as RequestPromise from 'request-promise'; import { Doc, DocListCast, DocListCastAsync, HierarchyMapping, ReverseHierarchyMap } from '../../fields/Doc'; import { AclAdmin, AclPrivate, DocAcl, DocData } from '../../fields/DocSymbols'; +import { FieldLoader } from '../../fields/FieldLoader'; import { Id } from '../../fields/FieldSymbols'; import { StrCast } from '../../fields/Types'; import { distributeAcls, GetEffectiveAcl, normalizeEmail, SharingPermissions, TraceMobx } from '../../fields/util'; @@ -23,6 +24,7 @@ import { GroupManager, UserOptions } from './GroupManager'; import { GroupMemberView } from './GroupMemberView'; import { LinkManager } from './LinkManager'; import { SelectionManager } from './SelectionManager'; +import { SettingsManager } from './SettingsManager'; import './SharingManager.scss'; import { undoable } from './UndoManager'; @@ -136,6 +138,7 @@ export class SharingManager extends React.Component<{}> { this.populating = true; const userList = await RequestPromise.get(Utils.prepend('/getUsers')); const raw = (JSON.parse(userList) as User[]).filter(user => user.email !== 'guest' && user.email !== Doc.CurrentUserEmail); + runInAction(() => (FieldLoader.ServerLoadStatus.message = 'users')); const docs = await DocServer.GetRefFields(raw.reduce((list, user) => [...list, user.sharingDocumentId, user.linkDatabaseId], [] as string[])); raw.map( action((newUser: User) => { @@ -144,7 +147,7 @@ export class SharingManager extends React.Component<{}> { if (sharingDoc instanceof Doc && linkDatabase instanceof Doc) { if (!this.users.find(user => user.user.email === newUser.email)) { this.users.push({ user: newUser, sharingDoc, linkDatabase, userColor: StrCast(sharingDoc.userColor) }); - LinkManager.addLinkDB(linkDatabase); + //LinkManager.addLinkDB(linkDatabase); } } }) @@ -525,10 +528,10 @@ export class SharingManager extends React.Component<{}> { const permissions = uniform ? StrCast(targetDoc?.[groupKey]) : '-multiple-'; return !permissions ? null : ( -
+
{StrCast(group.title)}
  - {group instanceof Doc ? } size={Size.XSMALL} color={StrCast(Doc.UserDoc().userColor)} onClick={action(() => (GroupManager.Instance.currentGroup = group))} /> : null} + {group instanceof Doc ? } size={Size.XSMALL} color={SettingsManager.Instance.userColor} onClick={action(() => (GroupManager.Instance.currentGroup = group))} /> : null}
{admin || this.myDocAcls ? ( setter(e.target.value)} onKeyPress={e => e.stopPropagation()} />
this.upDownButtons('up', key)))}> - +
this.upDownButtons('down', key)))}> - +
@@ -963,10 +932,10 @@ export class PropertiesView extends React.Component { setter(e.target.value)} />
this.upDownButtons('up', key)))}> - +
this.upDownButtons('down', key)))}> - +
@@ -983,7 +952,7 @@ export class PropertiesView extends React.Component { this.openSharing = false; this.openLayout = false; this.openFilters = false; - } + }; @computed get widthAndDash() { return ( @@ -1065,64 +1034,45 @@ export class PropertiesView extends React.Component { } getNumber = (label: string, unit: string, min: number, max: number, number: number, setNumber: any) => { - return
- - -
- } + return ( +
+ + +
+ ); + }; @computed get transformEditor() { return (
{this.isInk ? this.controlPointsButton : null} {this.getNumber( - "Height", - " px", + 'Height', + ' px', 0, 1000, Number(this.shapeHgt), undoable((val: string) => !isNaN(Number(val)) && (this.shapeHgt = val), 'set height') )} {this.getNumber( - "Width", - " px", + 'Width', + ' px', 0, 1000, Number(this.shapeWid), undoable((val: string) => !isNaN(Number(val)) && (this.shapeWid = val), 'set width') )} {this.getNumber( - "X Coordinate", - " px", + 'X Coordinate', + ' px', -2000, 2000, Number(this.shapeXps), undoable((val: string) => !isNaN(Number(val)) && (this.shapeXps = val), 'set x coord') )} {this.getNumber( - "Y Coordinate", - " px", + 'Y Coordinate', + ' px', -2000, 2000, Number(this.shapeYps), @@ -1133,38 +1083,44 @@ export class PropertiesView extends React.Component { } @computed get optionsSubMenu() { - return } - inSection={this.inOptions} - isOpen={this.openOptions} - setInSection={(bool) => this.inOptions = bool} - setIsOpen={(bool) => this.openOptions = bool} - onDoubleClick={() => this.onDoubleClick()} - /> + return ( + } + inSection={this.inOptions} + isOpen={this.openOptions} + setInSection={bool => (this.inOptions = bool)} + setIsOpen={bool => (this.openOptions = bool)} + onDoubleClick={() => this.onDoubleClick()} + /> + ); } @computed get sharingSubMenu() { - return - {/*
*/} -
- Layout Permissions - (this.layoutDocAcls = !this.layoutDocAcls))} checked={this.layoutDocAcls} /> -
- {/*
{"Re-distribute sharing settings"}
}> + return ( + + {/*
*/} +
+ Layout Permissions + (this.layoutDocAcls = !this.layoutDocAcls))} checked={this.layoutDocAcls} /> +
+ {/*
{"Re-distribute sharing settings"}
}>
*/} - {/*
*/} - {this.sharingTable} - } - isOpen={this.openSharing} - setIsOpen={(bool) => this.openSharing = bool} - onDoubleClick={() => this.onDoubleClick()} - /> + {/*
*/} + {this.sharingTable} + + } + isOpen={this.openSharing} + setIsOpen={bool => (this.openSharing = bool)} + onDoubleClick={() => this.onDoubleClick()} + /> + ); } /** @@ -1192,15 +1148,19 @@ export class PropertiesView extends React.Component { }; @computed get filtersSubMenu() { - return - -
} - isOpen={this.openFilters} - setIsOpen={(bool) => this.openFilters = bool} - onDoubleClick={() => this.onDoubleClick()} - /> + return ( + + +
+ } + isOpen={this.openFilters} + setIsOpen={bool => (this.openFilters = bool)} + onDoubleClick={() => this.onDoubleClick()} + /> + ); } @computed get inkSubMenu() { @@ -1208,68 +1168,42 @@ export class PropertiesView extends React.Component { return ( <> - this.openAppearance = bool} - onDoubleClick={() => this.onDoubleClick()} - /> - this.openTransform = bool} - onDoubleClick={() => this.onDoubleClick()} - /> + (this.openAppearance = bool)} onDoubleClick={() => this.onDoubleClick()} /> + (this.openTransform = bool)} onDoubleClick={() => this.onDoubleClick()} /> ); } @computed get fieldsSubMenu() { - return { - Doc.noviceMode ? this.noviceFields : this.expandedField} -
} - isOpen={this.openFields} - setIsOpen={(bool) => this.openFields = bool} - onDoubleClick={() => this.onDoubleClick()} - /> + return ( + {Doc.noviceMode ? this.noviceFields : this.expandedField}
} + isOpen={this.openFields} + setIsOpen={bool => (this.openFields = bool)} + onDoubleClick={() => this.onDoubleClick()} + /> + ); } @computed get contextsSubMenu() { - return 0 ? this.contexts : "There are no other contexts."} - isOpen={this.openContexts} - setIsOpen={(bool) => this.openContexts = bool} - onDoubleClick={() => this.onDoubleClick()} - /> + return ( + 0 ? this.contexts : 'There are no other contexts.'} + isOpen={this.openContexts} + setIsOpen={bool => (this.openContexts = bool)} + onDoubleClick={() => this.onDoubleClick()} + /> + ); } - - - - @computed get linksSubMenu() { - return 0 ? this.links : "There are no current links." } - isOpen={this.openLinks} - setIsOpen={(bool) => this.openLinks = bool} - onDoubleClick={() => this.onDoubleClick()} - /> + return 0 ? this.links : 'There are no current links.'} isOpen={this.openLinks} setIsOpen={bool => (this.openLinks = bool)} onDoubleClick={() => this.onDoubleClick()} />; } @computed get layoutSubMenu() { - return this.openLayout = bool} - onDoubleClick={() => this.onDoubleClick()} - /> + return (this.openLayout = bool)} onDoubleClick={() => this.onDoubleClick()} />; } @computed get description() { @@ -1470,224 +1404,226 @@ export class PropertiesView extends React.Component { if (scale > 1) scale = 1; this.sourceAnchor && (this.sourceAnchor.followLinkZoomScale = scale); }; - + @computed get linkProperties() { const zoom = Number((NumCast(this.sourceAnchor?.followLinkZoomScale, 1) * 100).toPrecision(3)); const targZoom = this.sourceAnchor?.followLinkZoom; const indent = 30; const hasSelectedAnchor = LinkManager.Links(this.sourceAnchor).includes(LinkManager.currentLink!); - return <> -
-
-

Relationship

- {this.editRelationship} -
-
-

Description

- {this.editDescription} -
-
-

Show link

- -
-
-

Auto-move anchors

- -
-
-

Display arrow

- -
-
- {!hasSelectedAnchor ? null : ( -
-
-

Follow by

- -
-
-

Animation

- -
- {this.animationDirection(PresEffectDirection.Left, 'angle-right', 1, 2, {})} - {this.animationDirection(PresEffectDirection.Right, 'angle-left', 3, 2, {})} - {this.animationDirection(PresEffectDirection.Top, 'angle-down', 2, 1, {})} - {this.animationDirection(PresEffectDirection.Bottom, 'angle-up', 2, 3, {})} - {this.animationDirection(PresEffectDirection.Center, '', 2, 2, { width: 10, height: 10, alignSelf: 'center' })} + return ( + <> +
+
+

Relationship

+ {this.editRelationship} +
+
+

Description

+ {this.editDescription} +
+
+

Show link

+ +
+
+

Auto-move anchors

+ +
+
+

Display arrow

+
- {PresBox.inputter( - '0.1', - '0.1', - '10', - NumCast(this.sourceAnchor?.followLinkTransitionTime) / 1000, - true, - (val: string) => PresBox.SetTransitionTime(val, (timeInMS: number) => this.sourceAnchor && (this.sourceAnchor.followLinkTransitionTime = timeInMS)), - indent - )}{' '} -
-
Fast
-
Slow
-
{' '} -
-

Play Target Audio

- -
-
-

Zoom Text Selections

- -
-
-

Toggle Follow to Outer Context

- -
-
-

Toggle Target (Show/Hide)

- -
-
-

Ease Transitions

- -
-
-

Capture Offset to Target

- -
-
-

Center Target (no zoom)

- -
-
-

Zoom %

-
- -
-
this.setZoom(String(zoom), 0.1))}> - + {!hasSelectedAnchor ? null : ( +
+
+

Follow by

+ +
+
+

Animation

+ +
+ {this.animationDirection(PresEffectDirection.Left, 'angle-right', 1, 2, {})} + {this.animationDirection(PresEffectDirection.Right, 'angle-left', 3, 2, {})} + {this.animationDirection(PresEffectDirection.Top, 'angle-down', 2, 1, {})} + {this.animationDirection(PresEffectDirection.Bottom, 'angle-up', 2, 3, {})} + {this.animationDirection(PresEffectDirection.Center, '', 2, 2, { width: 10, height: 10, alignSelf: 'center' })}
-
this.setZoom(String(zoom), -0.1))}> - +
+ {PresBox.inputter( + '0.1', + '0.1', + '10', + NumCast(this.sourceAnchor?.followLinkTransitionTime) / 1000, + true, + (val: string) => PresBox.SetTransitionTime(val, (timeInMS: number) => this.sourceAnchor && (this.sourceAnchor.followLinkTransitionTime = timeInMS)), + indent + )}{' '} +
+
Fast
+
Slow
+
{' '} +
+

Play Target Audio

+ +
+
+

Zoom Text Selections

+ +
+
+

Toggle Follow to Outer Context

+ +
+
+

Toggle Target (Show/Hide)

+ +
+
+

Ease Transitions

+ +
+
+

Capture Offset to Target

+ +
+
+

Center Target (no zoom)

+ +
+
+

Zoom %

+
+ +
+
this.setZoom(String(zoom), 0.1))}> + +
+
this.setZoom(String(zoom), -0.1))}> + +
+
+
+ {!targZoom ? null : PresBox.inputter('0', '1', '100', zoom, true, this.setZoom, 30)} +
+
0%
+
100%
+
{' '}
- -
- {!targZoom ? null : PresBox.inputter('0', '1', '100', zoom, true, this.setZoom, 30)} -
-
0%
-
100%
-
{' '} -
- )} - + )} + + ); } /** @@ -1723,23 +1659,20 @@ export class PropertiesView extends React.Component { width: this.props.width, minWidth: this.props.width, }}> -
+
Properties
-
window.open('https://brown-dash.github.io/Dash-Documentation/')}> -
- +
window.open('https://brown-dash.github.io/Dash-Documentation/')}> + {' '} +
-
{this.editableTitle}
-
{this.currentType}
+
{this.currentType}
{this.contextsSubMenu} {this.linksSubMenu} - {!this.selectedDoc || !LinkManager.currentLink || (!hasSelectedAnchor && this.selectedDoc !== LinkManager.currentLink) ? null : ( - this.linkProperties - )} + {!this.selectedDoc || !LinkManager.currentLink || (!hasSelectedAnchor && this.selectedDoc !== LinkManager.currentLink) ? null : this.linkProperties} {this.inkSubMenu} {this.optionsSubMenu} {this.fieldsSubMenu} @@ -1760,7 +1693,6 @@ export class PropertiesView extends React.Component { Presentation
- {this.editableTitle}
{PresBox.Instance.selectedArray.size} selected
@@ -1772,7 +1704,7 @@ export class PropertiesView extends React.Component {
(this.openPresTransitions = !this.openPresTransitions))} style={{ backgroundColor: this.openPresTransitions ? 'black' : '' }}>     Transitions
- +
{this.openPresTransitions ?
{PresBox.Instance.transitionDropdown}
: null} @@ -1786,7 +1718,7 @@ export class PropertiesView extends React.Component { style={{ backgroundColor: this.openPresTransitions ? 'black' : '' }}>     Visibilty
- +
{this.openPresVisibilityAndDuration ?
{PresBox.Instance.visibiltyDurationDropdown}
: null} @@ -1797,7 +1729,7 @@ export class PropertiesView extends React.Component {
(this.openPresProgressivize = !this.openPresProgressivize))} style={{ backgroundColor: this.openPresTransitions ? 'black' : '' }}>     Progressivize
- +
{this.openPresProgressivize ?
{PresBox.Instance.progressivizeDropdown}
: null} @@ -1808,7 +1740,7 @@ export class PropertiesView extends React.Component {
(this.openSlideOptions = !this.openSlideOptions))} style={{ backgroundColor: this.openSlideOptions ? 'black' : '' }}>     {type === DocumentType.AUDIO ? 'Audio Options' : 'Video Options'}
- +
{this.openSlideOptions ?
{PresBox.Instance.mediaOptionsDropdown}
: null} diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index bbbad3690..94748e884 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -22,7 +22,7 @@ import { DocumentViewProps } from './nodes/DocumentView'; import { FieldViewProps } from './nodes/FieldView'; import { KeyValueBox } from './nodes/KeyValueBox'; import { SliderBox } from './nodes/SliderBox'; -import { BsArrowDown, BsArrowUp, BsArrowDownUp } from 'react-icons/bs' +import { BsArrowDown, BsArrowUp, BsArrowDownUp } from 'react-icons/bs'; import './StyleProvider.scss'; import React = require('react'); @@ -161,7 +161,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt = StrCast(doc?.[fieldKey + 'color'], StrCast(doc?._color)); @@ -208,12 +208,10 @@ export function DefaultStyleProvider(doc: Opt, props: Opt, props: Opt { @observable static HideInline: boolean; @observable static Expand: boolean; render() { - const background = UndoManager.batchCounter.get() ? 'yellow' : StrCast(Doc.UserDoc().userBackgroundColor) + const background = UndoManager.batchCounter.get() ? 'yellow' : SettingsManager.Instance.userBackgroundColor; return this.props.inline && UndoStack.HideInline ? null : (
- r?.scroll({ behavior: 'auto', top: r?.scrollHeight + 20 })} - style={{ - background: background, - color: isDark(background) ? Colors.LIGHT_GRAY : Colors.DARK_GRAY - }}> - {UndoManager.undoStackNames.map((name, i) => ( -
-
{name.replace(/[^\.]*\./, '')}
-
- ))} - {Array.from(UndoManager.redoStackNames) - .reverse() - .map((name, i) => ( +
r?.scroll({ behavior: 'auto', top: r?.scrollHeight + 20 })} + style={{ + background: background, + color: isDark(background) ? Colors.LIGHT_GRAY : Colors.DARK_GRAY, + }}> + {UndoManager.undoStackNames.map((name, i) => (
-
- {name.replace(/[^\.]*\./, '')} -
+
{name.replace(/[^\.]*\./, '')}
- ))} -
+ ))} + {Array.from(UndoManager.redoStackNames) + .reverse() + .map((name, i) => ( +
+
+ {name.replace(/[^\.]*\./, '')} +
+
+ ))} +
} />
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 16982595d..0052c4196 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -164,7 +164,7 @@ export class CollectionDockingView extends CollectionSubView() { public static AddSplit(document: Doc, pullSide: OpenWhereMod, stack?: any, panelName?: string, keyValue?: boolean) { if (document?._type_collection === CollectionViewType.Docking && !keyValue) return DashboardView.openDashboard(document); if (!CollectionDockingView.Instance) return false; - const tab = Array.from(CollectionDockingView.Instance.tabMap).find(tab => tab.DashDoc === document && !keyValue); + const tab = Array.from(CollectionDockingView.Instance.tabMap).find(tab => tab.DashDoc === document && !tab.contentItem.config.props.keyValue && !keyValue); if (tab) { tab.header.parent.setActiveContentItem(tab.contentItem); return true; @@ -466,7 +466,10 @@ export class CollectionDockingView extends CollectionSubView() { this._flush = this._flush ?? UndoManager.StartBatch('tab movement'); if (tab.DashDoc && ![DocumentType.PRES].includes(tab.DashDoc?.type) && !tab.contentItem.config.props.keyValue) { Doc.AddDocToList(Doc.MyHeaderBar, 'data', tab.DashDoc); - Doc.AddDocToList(Doc.MyRecentlyClosed, 'data', tab.DashDoc, undefined, true, true); + // if you close a tab that is not embedded somewhere else (an embedded Doc can be opened simultaneously in a tab), then add the tab to recently closed + if (tab.DashDoc.embedContainer === this.rootDoc) tab.DashDoc.embedContainer = undefined; + if (!tab.DashDoc.embedContainer) Doc.AddDocToList(Doc.MyRecentlyClosed, 'data', tab.DashDoc, undefined, true, true); + Doc.RemoveDocFromList(Doc.GetProto(tab.DashDoc), 'proto_embeddings', tab.DashDoc); } if (CollectionDockingView.Instance) { const dview = CollectionDockingView.Instance.props.Document; diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 5135cfb57..f65e8698f 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -181,7 +181,7 @@ export class CollectionMenu extends AntimodeMenu {
{this.contMenuButtons} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index a5c276125..056204ad3 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -669,7 +669,6 @@ export class CollectionStackingView extends CollectionSubView { return NumCast(Cast(PresBox.Instance.activeItem.presentationTargetDoc, Doc, null)._currentFrame); }; static Activate = (tabDoc: Doc) => { - const tab = Array.from(CollectionDockingView.Instance?.tabMap!).find(tab => tab.DashDoc === tabDoc); + const tab = Array.from(CollectionDockingView.Instance?.tabMap!).find(tab => tab.DashDoc === tabDoc && !tab.contentItem.config.props.keyValue); tab?.header.parent.setActiveContentItem(tab.contentItem); // glr: Panning does not work when this is set - (this line is for trying to make a tab that is not topmost become topmost) return tab !== undefined; }; diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index fb23fc7f1..6e0ccd4be 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -127,7 +127,7 @@ export class TreeView extends React.Component { : this.props.treeView.fileSysMode ? this.doc.isFolder ? this.fieldKey - : 'embeddings' // for displaying + : 'data' // file system folders display their contents (data). used to be they displayed their embeddings but now its a tree structure and not a flat list : this.props.treeView.outlineMode || this.childDocs ? this.fieldKey : Doc.noviceMode diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 090cf356c..7c53bfdbe 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -377,7 +377,6 @@ export class MarqueeView extends React.Component { Doc.GetProto(doc).data = new List(selected); Doc.GetProto(doc).title = makeGroup ? 'grouping' : 'nested freeform'; - !this.props.isAnnotationOverlay && Doc.AddFileOrphan(Doc.GetProto(doc)); doc._freeform_panX = doc._freeform_panY = 0; return doc; })(Doc.MakeCopy(Doc.UserDoc().emptyCollection as Doc, true)); diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 79842047b..256377758 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -197,7 +197,6 @@ ScriptingGlobals.add(function toggleCharStyle(charStyle: attrname, checkResult?: }); export function checkInksToGroup() { - // console.log("getting here to inks group"); if (Doc.ActiveTool === InkTool.Write) { CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => { // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those diff --git a/src/client/views/newlightbox/ExploreView/ExploreView.tsx b/src/client/views/newlightbox/ExploreView/ExploreView.tsx index 44a0bcd5f..a1d6375c4 100644 --- a/src/client/views/newlightbox/ExploreView/ExploreView.tsx +++ b/src/client/views/newlightbox/ExploreView/ExploreView.tsx @@ -12,14 +12,11 @@ export const ExploreView = (props: IExploreView) => {
{recs && recs.map(rec => { - console.log(rec.embedding, bounds); const x_bound: number = Math.max(Math.abs(bounds.max_x), Math.abs(bounds.min_x)); const y_bound: number = Math.max(Math.abs(bounds.max_y), Math.abs(bounds.min_y)); - console.log(x_bound, y_bound); if (rec.embedding) { const x = (rec.embedding.x / x_bound) * 50; const y = (rec.embedding.y / y_bound) * 50; - console.log(x, y); return (
{}} style={{ top: `calc(50% + ${y}%)`, left: `calc(50% + ${x}%)` }}> {rec.title} diff --git a/src/client/views/newlightbox/components/Recommendation/Recommendation.tsx b/src/client/views/newlightbox/components/Recommendation/Recommendation.tsx index b9d05c531..2c2f04b9f 100644 --- a/src/client/views/newlightbox/components/Recommendation/Recommendation.tsx +++ b/src/client/views/newlightbox/components/Recommendation/Recommendation.tsx @@ -22,7 +22,6 @@ export const Recommendation = (props: IRecommendation) => { doc = docView.rootDoc; } } else if (data) { - console.log(data, type); switch (type) { case 'YouTube': console.log('create ', type, 'document'); diff --git a/src/client/views/nodes/DataVizBox/utils/D3Utils.ts b/src/client/views/nodes/DataVizBox/utils/D3Utils.ts index e1ff6f8eb..10bfb0c64 100644 --- a/src/client/views/nodes/DataVizBox/utils/D3Utils.ts +++ b/src/client/views/nodes/DataVizBox/utils/D3Utils.ts @@ -34,7 +34,6 @@ export const createLineGenerator = (xScale: d3.ScaleLinear, height: number, xScale: d3.ScaleLinear) => { - console.log('x axis creator being called'); g.attr('class', 'x-axis').attr('transform', `translate(0,${height})`).call(d3.axisBottom(xScale).tickSize(15)); }; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 70d2f95ea..d379b2b52 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,5 +1,5 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; -import { action, computed, IReactionDisposer, observable, reaction, runInAction, trace } from 'mobx'; +import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import { Bounce, Fade, Flip, LightSpeed, Roll, Rotate, Zoom } from 'react-reveal'; @@ -47,7 +47,6 @@ import { DocumentLinksButton } from './DocumentLinksButton'; import './DocumentView.scss'; import { FieldViewProps } from './FieldView'; import { FormattedTextBox } from './formattedText/FormattedTextBox'; -import { KeyValueBox } from './KeyValueBox'; import { LinkAnchorBox } from './LinkAnchorBox'; import { PresEffect, PresEffectDirection } from './trails'; import { PinProps, PresBox } from './trails/PresBox'; diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 86191de63..d69009415 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -4,7 +4,7 @@ import { action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import wiki from 'wikijs'; import { Doc, DocCastAsync, Opt } from '../../../fields/Doc'; -import { Height, Width } from '../../../fields/DocSymbols'; +import { DirectLinks, Height, Width } from '../../../fields/DocSymbols'; import { Cast, DocCast, NumCast, PromiseValue, StrCast } from '../../../fields/Types'; import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnNone, setupMoveUpEvents } from '../../../Utils'; import { DocServer } from '../../DocServer'; diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index de0b57fd7..4919ee94c 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -61,7 +61,6 @@ const script = document.createElement('script'); script.defer = true; script.async = true; script.src = `https://maps.googleapis.com/maps/api/js?key=${apiKey}&libraries=places,drawing`; -console.log(script.src); document.head.appendChild(script); /** diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx index 312b3c619..bbf56bdf9 100644 --- a/src/client/views/nodes/ScreenshotBox.tsx +++ b/src/client/views/nodes/ScreenshotBox.tsx @@ -224,7 +224,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent aud_chunks.push(e.data); this._audioRec.onstop = async (e: any) => { - const [{ result }] = await Networking.UploadFilesToServer(aud_chunks.map((file: any) => ({file}))); + const [{ result }] = await Networking.UploadFilesToServer(aud_chunks.map((file: any) => ({ file }))); if (!(result instanceof Error)) { this.dataDoc[this.props.fieldKey + '-audio'] = new AudioField(result.accessPaths.agnostic.client); } @@ -235,9 +235,8 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent (this.dataDoc[this.props.fieldKey + '-recordingStart'] = new DateField(new Date())); this._videoRec.ondataavailable = (e: any) => vid_chunks.push(e.data); this._videoRec.onstop = async (e: any) => { - console.log('screenshotbox: upload'); const file = new File(vid_chunks, `${this.rootDoc[Id]}.mkv`, { type: vid_chunks[0].type, lastModified: Date.now() }); - const [{ result }] = await Networking.UploadFilesToServer({file}); + const [{ result }] = await Networking.UploadFilesToServer({ file }); this.dataDoc[this.fieldKey + '_duration'] = (new Date().getTime() - this.recordingStart!) / 1000; if (!(result instanceof Error)) { // convert this screenshotBox into normal videoBox diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx index 3ad3c911d..7c8a1849e 100644 --- a/src/client/views/nodes/ScriptingBox.tsx +++ b/src/client/views/nodes/ScriptingBox.tsx @@ -610,7 +610,6 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent this.handleToken(token), component: (blob: any) => { - console.log('Blob', blob); return this.renderFuncListElement(blob.entity); }, output: (item: any, trigger: any) => { @@ -621,7 +620,6 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent this.handleToken(token), component: (blob: any) => { - console.log('Blob', blob); return this.renderFuncListElement(blob.entity); }, output: (item: any, trigger: any) => { diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 895bb80f0..1dcc445e8 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -96,6 +96,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent = React.createRef(); private _editorView: Opt; public _applyingChange: string = ''; + private _finishingLink = false; private _searchIndex = 0; private _lastTimedMark: Mark | undefined = undefined; private _cachedLinks: Doc[] = []; @@ -245,7 +246,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent m.type.name === schema.marks.noAutoLinkAnchor.name) && node.marks.find((m: Mark) => m.type.name === schema.marks.splitter.name)) { alink = alink ?? - (LinkManager.Links(this.Document).find(link => Doc.AreProtosEqual(Cast(link.link_anchor_1, Doc, null), this.rootDoc) && Doc.AreProtosEqual(Cast(link.link_anchor_2, Doc, null), target)) || - DocUtils.MakeLink(this.props.Document, target, { link_relationship: LinkManager.AutoKeywords })!); + (LinkManager.Links(this.rootDoc).find( + link => + Doc.AreProtosEqual(Cast(link.link_anchor_1, Doc, null), this.rootDoc) && // + Doc.AreProtosEqual(Cast(link.link_anchor_2, Doc, null), target) + ) || + DocUtils.MakeLink(this.rootDoc, target, { link_relationship: LinkManager.AutoKeywords })!); newAutoLinks.add(alink); const allAnchors = [{ href: Doc.localServerPath(target), title: 'a link', anchorId: this.props.Document[Id] }]; allAnchors.push(...(node.marks.find((m: Mark) => m.type.name === schema.marks.autoLinkAnchor.name)?.attrs.allAnchors ?? [])); @@ -840,7 +847,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent Doc.UserDoc().defaultTextLayout = new PrefetchProxy(this.rootDoc), icon: "eye" }); !Doc.noviceMode && @@ -1996,12 +2003,12 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { if (this.layoutDoc._layout_enableAltContentUI) { - const usePath = this.rootDoc[`${this.props.fieldKey}_usePath`]; + const usePath = this.rootDoc[`_${this.props.fieldKey}_usePath`]; this.rootDoc[`_${this.props.fieldKey}_usePath`] = usePath === undefined ? 'alternate' : usePath === 'alternate' ? 'alternate:hover' : undefined; } }; @computed get overlayAlternateIcon() { - const usePath = this.rootDoc[`${this.props.fieldKey}_usePath`]; + const usePath = this.rootDoc[`_${this.props.fieldKey}_usePath`]; return ( : ]] - // [[:Doc]] => hyperlink + // [[:docTitle]] => hyperlink // [[fieldKey]] => show field // [[fieldKey=value]] => show field and also set its value - // [[fieldKey:Doc]] => show field of doc + // [[fieldKey:docTitle]] => show field of doc new InputRule(new RegExp(/\[\[([a-zA-Z_\? \-0-9]*)(=[a-zA-Z_@\? /\-0-9]*)?(:[a-zA-Z_@:\.\? \-0-9]+)?\]\]$/), (state, match, start, end) => { const fieldKey = match[1]; - const docId = match[3]?.replace(':', ''); + const docTitle = match[3]?.replace(':', ''); const value = match[2]?.substring(1); const linkToDoc = (target: Doc) => { const rstate = this.TextBox.EditorView?.state; @@ -266,12 +266,12 @@ export class RichTextRules { } }; if (!fieldKey) { - if (docId) { - const target = DocServer.QUERY_SERVER_CACHE(docId); - if (target) setTimeout(() => linkToDoc(target)); - else DocServer.GetRefField(docId).then(docx => linkToDoc((docx instanceof Doc && docx) || Docs.Create.FreeformDocument([], { title: docId + '(auto)', _width: 500, _height: 500 }, docId))); - - return state.tr.deleteRange(end - 1, end).deleteRange(start, start + 3); + if (docTitle) { + const target = DocServer.FindDocByTitle(docTitle); + if (target) { + setTimeout(() => linkToDoc(target)); + return state.tr.deleteRange(end - 1, end).deleteRange(start, start + 3); + } } return state.tr; } @@ -279,8 +279,12 @@ export class RichTextRules { const num = value.match(/^[0-9.]$/); this.Document[DocData][fieldKey] = value === 'true' ? true : value === 'false' ? false : num ? Number(value) : value; } - const fieldView = state.schema.nodes.dashField.create({ fieldKey, docId, hideKey: false }); - return state.tr.setSelection(new TextSelection(state.doc.resolve(start), state.doc.resolve(end))).replaceSelectionWith(fieldView, true); + const target = DocServer.FindDocByTitle(docTitle); + if (target) { + const fieldView = state.schema.nodes.dashField.create({ fieldKey, docId: target[Id], hideKey: false }); + return state.tr.setSelection(new TextSelection(state.doc.resolve(start), state.doc.resolve(end))).replaceSelectionWith(fieldView, true); + } + return state.tr; }), // create a text display of a metadata field on this or another document, or create a hyperlink portal to another document diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx index b877cc36a..e35e011e2 100644 --- a/src/client/views/pdf/AnchorMenu.tsx +++ b/src/client/views/pdf/AnchorMenu.tsx @@ -17,6 +17,7 @@ import { EditorView } from 'prosemirror-view'; import './AnchorMenu.scss'; import { ColorPicker, Group, IconButton, Popup, Size, Toggle, ToggleType, Type } from 'browndash-components'; import { StrCast } from '../../../fields/Types'; +import { DocumentType } from '../../documents/DocumentTypes'; @observer export class AnchorMenu extends AntimodeMenu { @@ -262,7 +263,7 @@ export class AnchorMenu extends AntimodeMenu { colorPicker={this.highlightColor} color={StrCast(Doc.UserDoc().userColor)} /> - this.changeHighlightColor(color)} size={Size.XSMALL} /> + ); } @@ -287,7 +288,7 @@ export class AnchorMenu extends AntimodeMenu { canSummarize = (): boolean => { const docs = SelectionManager.Docs(); if (docs.length > 0) { - return docs.some(doc => doc.type === 'pdf' || doc.type === 'web'); + return docs.some(doc => doc.type === DocumentType.PDF || doc.type === DocumentType.WEB); } return false; }; diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index e911bd283..a28561107 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -18,6 +18,7 @@ import './SearchBox.scss'; import { fetchRecommendations } from '../newlightbox/utils'; import { IRecommendation, Recommendation } from '../newlightbox/components'; import { Colors } from '../global/globalEnums'; +import { SettingsManager } from '../../util/SettingsManager'; const DAMPENING_FACTOR = 0.9; const MAX_ITERATIONS = 25; @@ -218,7 +219,7 @@ export class SearchBox extends ViewBoxBaseComponent() { } @action static staticSearchCollection(rootDoc: Opt, query: string) { - const blockedTypes = [DocumentType.PRESELEMENT, DocumentType.CONFIG, DocumentType.KVP, DocumentType.FILTER, DocumentType.SEARCH, DocumentType.SEARCHITEM, DocumentType.FONTICON, DocumentType.BUTTON, DocumentType.SCRIPTING]; + const blockedTypes = [DocumentType.PRESELEMENT, DocumentType.CONFIG, DocumentType.KVP, DocumentType.SEARCH, DocumentType.FONTICON, DocumentType.BUTTON, DocumentType.SCRIPTING]; const blockedKeys = [ 'x', 'y', @@ -398,22 +399,21 @@ export class SearchBox extends ViewBoxBaseComponent() { if (query) { this.searchCollection(query); - const response = await fetchRecommendations('', query, [], true) - const recs = response.recommendations - const recommendations:IRecommendation[] = [] + const response = await fetchRecommendations('', query, [], true); + const recs = response.recommendations; + const recommendations: IRecommendation[] = []; for (const key in recs) { const title = recs[key].title; - console.log(title); - const url = recs[key].url - const type = recs[key].type - const text = recs[key].text - const transcript = recs[key].transcript - const previewUrl = recs[key].previewUrl - const embedding = recs[key].embedding - const distance = recs[key].distance - const source = recs[key].source - const related_concepts = recs[key].related_concepts - const docId = recs[key].doc_id + const url = recs[key].url; + const type = recs[key].type; + const text = recs[key].text; + const transcript = recs[key].transcript; + const previewUrl = recs[key].previewUrl; + const embedding = recs[key].embedding; + const distance = recs[key].distance; + const source = recs[key].source; + const related_concepts = recs[key].related_concepts; + const docId = recs[key].doc_id; recommendations.push({ title: title, data: url, @@ -425,11 +425,11 @@ export class SearchBox extends ViewBoxBaseComponent() { distance: Math.round(distance * 100) / 100, source: source, related_concepts: related_concepts, - docId: docId - }) + docId: docId, + }); } - const setRecommendations = action(() => this._recommendations = recommendations) - setRecommendations() + const setRecommendations = action(() => (this._recommendations = recommendations)); + setRecommendations(); } }; @@ -461,7 +461,7 @@ export class SearchBox extends ViewBoxBaseComponent() { */ @computed public get selectOptions() { - const selectValues = ['all', 'rtf', 'image', 'pdf', 'web', 'video', 'audio', 'collection']; + const selectValues = ['all', DocumentType.RTF, DocumentType.IMG, DocumentType.PDF, DocumentType.WEB, DocumentType.VID, DocumentType.AUDIO, DocumentType.COL]; return selectValues.map(value => (
); } }); - const recommendationsJSX: JSX.Element[] = this._recommendations.map((props) => ( - - )) + const recommendationsJSX: JSX.Element[] = this._recommendations.map(props => ); return ( -
+
{isLinkSearch ? null : ( {
filter.split(Doc.FilterSep)[0] === facetHeader && filter.split(Doc.FilterSep)[1] == facetValue) - ?.split(Doc.FilterSep)[2] === 'check' + checked={ + StrListCast(this.targetDoc._childFilters) + .find(filter => filter.split(Doc.FilterSep)[0] === facetHeader && filter.split(Doc.FilterSep)[1] == facetValue) + ?.split(Doc.FilterSep)[2] === 'check' } type={type} - onChange={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, e.target.checked ? 'check' : 'remove'), 'set filter')} + onChange={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, e.target.checked ? 'check' : 'remove'), 'set filter')} /> {facetValue}
); - }) - - case 'range': - const domain = renderInfoDomain; - if (domain){ - return( -
- Doc.setDocRangeFilter(this.targetDoc, facetHeader, values)} values={renderInfoRange!} > - {railProps => } - - {({ handles, activeHandleID, getHandleProps }) => ( -
- {handles.map((handle, i) => { - // const value = i === 0 ? defaultValues[0] : defaultValues[1]; - return ( -
- -
- ); - })} -
- )} -
- - {({ tracks, getTrackProps }) => ( -
- {tracks.map(({ id, source, target }) => ( - - ))} -
- )} -
- - {({ ticks }) => ( -
- {ticks.map(tick => ( - val.toString()} /> - ))} -
- )} -
-
-
- - ) - } + }); + + case 'range': + const domain = renderInfoDomain; + if (domain) { + return ( +
+ Doc.setDocRangeFilter(this.targetDoc, facetHeader, values)} + values={renderInfoRange!}> + {railProps => } + + {({ handles, activeHandleID, getHandleProps }) => ( +
+ {handles.map((handle, i) => { + // const value = i === 0 ? defaultValues[0] : defaultValues[1]; + return ( +
+ +
+ ); + })} +
+ )} +
+ + {({ tracks, getTrackProps }) => ( +
+ {tracks.map(({ id, source, target }) => ( + + ))} +
+ )} +
+ + {({ ticks }) => ( +
+ {ticks.map(tick => ( + val.toString()} /> + ))} +
+ )} +
+
+
+ ); + } - - - // case 'range' - // return domain is number[] for min and max - // onChange = { ... Doc.setDocRangeFilter(this.targetDoc, facetHeader, [extendedMinVal, extendedMaxVal] ) } - // - // OR - - // return
- // // domain is number[] for min and max - // - // domain is number[] for min and max + // onChange = { ... Doc.setDocRangeFilter(this.targetDoc, facetHeader, [extendedMinVal, extendedMaxVal] ) } + // + // OR + + // return
+ // // domain is number[] for min and max + // + // { + private _selectedDisposer?: IReactionDisposer; + @observable private _selectedIndex: number = 0; + + componentDidMount = () => { + this._selectedDisposer = reaction( + () => NumCast(this.props.thumbDoc.selectedIndex), + i => (this._selectedIndex = i), + { fireImmediately: true } + ); + }; + + componentWillUnmount = () => { + this._selectedDisposer?.(); + }; + + render() { + return ( +
+
+
+ window.screen.width} + PanelHeight={() => window.screen.height} + renderDepth={0} + isDocumentActive={returnTrue} + isContentActive={emptyFunction} + focus={emptyFunction} + docViewPath={returnEmptyDoclist} + styleProvider={returnEmptyString} + whenChildContentsActiveChanged={emptyFunction} + bringToFront={emptyFunction} + docFilters={returnEmptyFilter} + docRangeFilters={returnEmptyFilter} + searchFilterDocs={returnEmptyDoclist} + /> +
+
+
+
+ ); + } +} diff --git a/src/client/views/nodes/.QueryBox.scss.icloud b/src/client/views/nodes/.QueryBox.scss.icloud new file mode 100644 index 000000000..26ba46a75 Binary files /dev/null and b/src/client/views/nodes/.QueryBox.scss.icloud differ diff --git a/src/client/views/nodes/.QueryBox.tsx.icloud b/src/client/views/nodes/.QueryBox.tsx.icloud new file mode 100644 index 000000000..5930b1e0e Binary files /dev/null and b/src/client/views/nodes/.QueryBox.tsx.icloud differ diff --git a/src/fields/.ListSpec.ts.icloud b/src/fields/.ListSpec.ts.icloud new file mode 100644 index 000000000..2fbd1858e Binary files /dev/null and b/src/fields/.ListSpec.ts.icloud differ diff --git a/src/fields/IconField.ts b/src/fields/IconField.ts new file mode 100644 index 000000000..76c4ddf1b --- /dev/null +++ b/src/fields/IconField.ts @@ -0,0 +1,26 @@ +import { Deserializable } from "../client/util/SerializationHelper"; +import { serializable, primitive } from "serializr"; +import { ObjectField } from "./ObjectField"; +import { Copy, ToScriptString, ToString } from "./FieldSymbols"; + +@Deserializable("icon") +export class IconField extends ObjectField { + @serializable(primitive()) + readonly icon: string; + + constructor(icon: string) { + super(); + this.icon = icon; + } + + [Copy]() { + return new IconField(this.icon); + } + + [ToScriptString]() { + return "invalid"; + } + [ToString]() { + return "ICONfield"; + } +} diff --git a/src/fields/PresField.ts b/src/fields/PresField.ts new file mode 100644 index 000000000..f236a04fd --- /dev/null +++ b/src/fields/PresField.ts @@ -0,0 +1,6 @@ +//insert code here +import { ObjectField } from "./ObjectField"; + +export abstract class PresField extends ObjectField { + +} \ No newline at end of file diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index 584a7b432..c16a1c124 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -584,6 +584,7 @@ export class MobileInterface extends React.Component { y: 400, title: 'Collection ' + dashboardCount, }; + const freeformDoc = Doc.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions); const dashboardDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600 }], { title: `Dashboard ${dashboardCount}` }, id, 'row'); diff --git a/src/server/stats/.userLoginStats.csv.icloud b/src/server/stats/.userLoginStats.csv.icloud new file mode 100644 index 000000000..4a95297e8 Binary files /dev/null and b/src/server/stats/.userLoginStats.csv.icloud differ -- cgit v1.2.3-70-g09d2 From 2fcad5e8bd1412487b4fcacefdc12a2df5707638 Mon Sep 17 00:00:00 2001 From: eperelm2 Date: Thu, 24 Aug 2023 20:12:24 +0200 Subject: filter - trying to pull --- src/client/documents/Documents.ts | 135 ++++++++++++++++++--------------- src/client/util/.ClientUtils.ts.icloud | Bin 161 -> 0 bytes src/client/views/FilterPanel.tsx | 30 ++++++-- 3 files changed, 99 insertions(+), 66 deletions(-) delete mode 100644 src/client/util/.ClientUtils.ts.icloud (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 533df5c11..1988c6328 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -86,13 +86,18 @@ export class FInfo { class BoolInfo extends FInfo { fieldType? = 'boolean'; values?: boolean[] = [true, false]; + constructor(d: string, filterable?: boolean) { + super(d); + this.filterable = filterable; + } } class NumInfo extends FInfo { fieldType? = 'number'; values?: number[] = []; - constructor(d: string, readOnly?: boolean, values?: number[], filterable?: boolean) { + constructor(d: string, filterable?: boolean, readOnly?: boolean, values?: number[]) { super(d, readOnly); this.values = values; + this.filterable = filterable; } } class StrInfo extends FInfo { @@ -110,27 +115,32 @@ class DocInfo extends FInfo { constructor(d: string, filterable?: boolean, values?: Doc[]) { super(d, true); this.values = values; + this.filterable = filterable; } } class DimInfo extends FInfo { fieldType? = 'enumeration'; values? = [DimUnit.Pixel, DimUnit.Ratio]; readOnly = false; + filterable = false; } class PEInfo extends FInfo { fieldType? = 'enumeration'; values? = ['all', 'none']; readOnly = false; + filterable = false; } class DAInfo extends FInfo { fieldType? = 'enumeration'; values? = ['embed', 'copy', 'move', 'same', 'proto', 'none']; readOnly = false; + filterable = false; } class CTypeInfo extends FInfo { fieldType? = 'enumeration'; values? = Array.from(Object.keys(CollectionViewType)); readOnly = false; + filterable = false; } class DTypeInfo extends FInfo { fieldType? = 'enumeration'; @@ -140,6 +150,7 @@ class DTypeInfo extends FInfo { class DateInfo extends FInfo { fieldType? = 'date'; values?: DateField[] = []; + filterable = true; } class ListInfo extends FInfo { fieldType? = 'list'; @@ -158,23 +169,23 @@ type DATEt = DateInfo | number; type DTYPEt = DTypeInfo | string; export class DocumentOptions { // coordinate and dimensions depending on view - x?: NUMt = new NumInfo('x coordinate of document in a freeform view'); - y?: NUMt = new NumInfo('y coordinage of document in a freeform view'); - z?: NUMt = new NumInfo('whether document is in overlay (1) or not (0)', false, [1, 0]); - _dimMagnitude?: NUMt = new NumInfo("magnitude of collectionMulti{row,col} element's width or height"); + x?: NUMt = new NumInfo('x coordinate of document in a freeform view', false); + y?: NUMt = new NumInfo('y coordinage of document in a freeform view', false); + z?: NUMt = new NumInfo('whether document is in overlay (1) or not (0)', false, false, [1, 0]); + _dimMagnitude?: NUMt = new NumInfo("magnitude of collectionMulti{row,col} element's width or height", false); _dimUnit?: DIMt = new DimInfo("units of collectionMulti{row,col} element's width or height - 'px' or '*' for pixels or relative units"); - lat?: NUMt = new NumInfo('latitude coordinate for map views'); - lng?: NUMt = new NumInfo('longitude coordinate for map views'); - _timecodeToShow?: NUMt = new NumInfo('the time that a document should be displayed (e.g., when an annotation shows up as a video plays)'); - _timecodeToHide?: NUMt = new NumInfo('the time that a document should be hidden'); - _width?: NUMt = new NumInfo('displayed width of a document'); - _height?: NUMt = new NumInfo('displayed height of document'); - data_nativeWidth?: NUMt = new NumInfo('native width of data field contents (e.g., the pixel width of an image)'); - data_nativeHeight?: NUMt = new NumInfo('native height of data field contents (e.g., the pixel height of an image)'); - linearBtnWidth?: NUMt = new NumInfo('unexpanded width of a linear menu button (button "width" changes when it expands)'); - _nativeWidth?: NUMt = new NumInfo('native width of document contents (e.g., the pixel width of an image)'); - _nativeHeight?: NUMt = new NumInfo('native height of document contents (e.g., the pixel height of an image)'); - _nativeDimModifiable?: BOOLt = new BoolInfo('native dimensions can be modified using document decoration reizers'); + lat?: NUMt = new NumInfo('latitude coordinate for map views', false); + lng?: NUMt = new NumInfo('longitude coordinate for map views', false); + _timecodeToShow?: NUMt = new NumInfo('the time that a document should be displayed (e.g., when an annotation shows up as a video plays)', false); + _timecodeToHide?: NUMt = new NumInfo('the time that a document should be hidden', false); + _width?: NUMt = new NumInfo('displayed width of a document', true); + _height?: NUMt = new NumInfo('displayed height of document', true); + data_nativeWidth?: NUMt = new NumInfo('native width of data field contents (e.g., the pixel width of an image)', false); + data_nativeHeight?: NUMt = new NumInfo('native height of data field contents (e.g., the pixel height of an image)', false); + linearBtnWidth?: NUMt = new NumInfo('unexpanded width of a linear menu button (button "width" changes when it expands)', false); + _nativeWidth?: NUMt = new NumInfo('native width of document contents (e.g., the pixel width of an image)', false); + _nativeHeight?: NUMt = new NumInfo('native height of document contents (e.g., the pixel height of an image)', false); + _nativeDimModifiable?: BOOLt = new BoolInfo('native dimensions can be modified using document decoration reizers', false); _nativeHeightUnfrozen?: BOOLt = new BoolInfo('native height can be changed independent of width by dragging decoration resizers'); 'acl-Guest'?: string; // public permissions @@ -182,29 +193,29 @@ export class DocumentOptions { type?: DTYPEt = new DTypeInfo('type of document', true); type_collection?: COLLt = new CTypeInfo('how collection is rendered'); // sub type of a collection _type_collection?: COLLt = new CTypeInfo('how collection is rendered'); // sub type of a collection - title?: STRt = new StrInfo('title of document'); + title?: STRt = new StrInfo('title of document', true); caption?: RichTextField; author?: string; // STRt = new StrInfo('creator of document'); // bcz: don't change this. Otherwise, the userDoc's field Infos will have a FieldInfo assigned to its author field which will render it unreadable author_date?: DATEt = new DateInfo('date the document was created', true); annotationOn?: DOCt = new DocInfo('document annotated by this document', false); - color?: STRt = new StrInfo('foreground color data doc', true); - hidden?: BOOLt = new BoolInfo('whether the document is not rendered by its collection'); - backgroundColor?: STRt = new StrInfo('background color for data doc'); - opacity?: NUMt = new NumInfo('document opacity'); - viewTransitionTime?: NUMt = new NumInfo('transition duration for view parameters'); - dontRegisterView?: BOOLt = new BoolInfo('are views of this document registered so that they can be found when following links, etc'); + color?: STRt = new StrInfo('foreground color data doc', false); + hidden?: BOOLt = new BoolInfo('whether the document is not rendered by its collection', false); + backgroundColor?: STRt = new StrInfo('background color for data doc', false); + opacity?: NUMt = new NumInfo('document opacity', false); + viewTransitionTime?: NUMt = new NumInfo('transition duration for view parameters', false); + dontRegisterView?: BOOLt = new BoolInfo('are views of this document registered so that they can be found when following links, etc', false); _undoIgnoreFields?: List; //'fields that should not be added to the undo stack (opacity for Undo/Redo/and sidebar) AND whether modifications to document are undoable (true for linearview menu buttons to prevent open/close from entering undo stack)' undoIgnoreFields?: List; //'fields that should not be added to the undo stack (opacity for Undo/Redo/and sidebar) AND whether modifications to document are undoable (true for linearview menu buttons to prevent open/close from entering undo stack)' - _headerHeight?: NUMt = new NumInfo('height of document header used for displaying title'); - _headerFontSize?: NUMt = new NumInfo('font size of header of custom notes'); + _headerHeight?: NUMt = new NumInfo('height of document header used for displaying title', false); + _headerFontSize?: NUMt = new NumInfo('font size of header of custom notes', false); _headerPointerEvents?: PEVt = new PEInfo('types of events the header of a custom text document can consume'); _lockedPosition?: BOOLt = new BoolInfo("lock the x,y coordinates of the document so that it can't be dragged"); _lockedTransform?: BOOLt = new BoolInfo('lock the freeform_panx,freeform_pany and scale parameters of the document so that it be panned/zoomed'); layout?: string | Doc; // default layout string or template document - layout_keyValue?: STRt = new StrInfo('layout definition for showing keyValue view of document'); - layout_explainer?: STRt = new StrInfo('explanation displayed at top of a collection to describe its purpose'); - layout_headerButton?: DOCt = new DocInfo('the (button) Doc to display at the top of a collection.'); + layout_keyValue?: STRt = new StrInfo('layout definition for showing keyValue view of document', false); + layout_explainer?: STRt = new StrInfo('explanation displayed at top of a collection to describe its purpose', false); + layout_headerButton?: DOCt = new DocInfo('the (button) Doc to display at the top of a collection.', false); layout_disableBrushing?: BOOLt = new BoolInfo('whether to suppress border highlighting'); layout_unrendered?: BOOLt = new BoolInfo('denotes an annotation that is not rendered with a DocumentView (e.g, rtf/pdf text selections and links to scroll locations in web/pdf)'); layout_hideOpenButton?: BOOLt = new BoolInfo('whether to hide the open full screen button when selected'); @@ -216,33 +227,33 @@ export class DocumentOptions { layout_hideDecorationTitle?: BOOLt = new BoolInfo('whether to suppress the document decortations title when selected'); layout_borderRounding?: string; layout_boxShadow?: string; // box-shadow css string OR "standard" to use dash standard box shadow - layout_maxAutoHeight?: NUMt = new NumInfo('maximum height for newly created (eg, from pasting) text documents'); + layout_maxAutoHeight?: NUMt = new NumInfo('maximum height for newly created (eg, from pasting) text documents', false); _layout_autoHeight?: BOOLt = new BoolInfo('whether document automatically resizes vertically to display contents'); - _layout_curPage?: NUMt = new NumInfo('current page of a PDF or other? paginated document'); - _layout_currentTimecode?: NUMt = new NumInfo('the current timecode of a time-based document (e.g., current time of a video) value is in seconds'); + _layout_curPage?: NUMt = new NumInfo('current page of a PDF or other? paginated document', false); + _layout_currentTimecode?: NUMt = new NumInfo('the current timecode of a time-based document (e.g., current time of a video) value is in seconds', false); _layout_hideContextMenu?: BOOLt = new BoolInfo('whether the context menu can be shown'); _layout_fitWidth?: BOOLt = new BoolInfo('whether document should scale its contents to fit its rendered width or not (e.g., for PDFviews)'); _layout_fitContentsToBox?: BOOLt = new BoolInfo('whether a freeformview should zoom/scale to create a shrinkwrapped view of its content'); - _layout_fieldKey?: STRt = new StrInfo('the field key containing the current layout definition'); + _layout_fieldKey?: STRt = new StrInfo('the field key containing the current layout definition', false); _layout_enableAltContentUI?: BOOLt = new BoolInfo('whether to show alternate content button'); _layout_showTitle?: string; // field name to display in header (:hover is an optional suffix) _layout_showSidebar?: BOOLt = new BoolInfo('whether an annotationsidebar should be displayed for text docuemnts'); _layout_showCaption?: string; // which field to display in the caption area. leave empty to have no caption _chromeHidden?: BOOLt = new BoolInfo('whether the editing chrome for a document is hidden'); - _gridGap?: NUMt = new NumInfo('gap between items in masonry view'); - _xMargin?: NUMt = new NumInfo('gap between left edge of document and start of masonry/stacking layouts'); - _yMargin?: NUMt = new NumInfo('gap between top edge of dcoument and start of masonry/stacking layouts'); - _xPadding?: NUMt = new NumInfo('x padding'); - _yPadding?: NUMt = new NumInfo('y padding'); + _gridGap?: NUMt = new NumInfo('gap between items in masonry view', false); + _xMargin?: NUMt = new NumInfo('gap between left edge of document and start of masonry/stacking layouts', false); + _yMargin?: NUMt = new NumInfo('gap between top edge of dcoument and start of masonry/stacking layouts', false); + _xPadding?: NUMt = new NumInfo('x padding', false); + _yPadding?: NUMt = new NumInfo('y padding', false); _singleLine?: boolean; // whether label box is restricted to one line of text _createDocOnCR?: boolean; // whether carriage returns and tabs create new text documents - _columnWidth?: NUMt = new NumInfo('width of table column'); + _columnWidth?: NUMt = new NumInfo('width of table column', false); _columnsHideIfEmpty?: BOOLt = new BoolInfo('whether stacking view column headings should be hidden'); - _caption_xMargin?: NUMt = new NumInfo('x margin of caption inside of a carousel collection', true); - _caption_yMargin?: NUMt = new NumInfo('y margin of caption inside of a carousel collection', true); - icon_nativeWidth?: NUMt = new NumInfo('native width of icon view', true); - icon_nativeHeight?: NUMt = new NumInfo('native height of icon view', true); + _caption_xMargin?: NUMt = new NumInfo('x margin of caption inside of a carousel collection', false, true); + _caption_yMargin?: NUMt = new NumInfo('y margin of caption inside of a carousel collection', false, true); + icon_nativeWidth?: NUMt = new NumInfo('native width of icon view', false, true); + icon_nativeHeight?: NUMt = new NumInfo('native height of icon view', false, true); _text_fontSize?: string; _text_fontFamily?: string; _text_fontWeight?: string; @@ -250,11 +261,11 @@ export class DocumentOptions { infoWindowOpen?: BOOLt = new BoolInfo('whether info window corresponding to pin is open (on MapDocuments)'); _carousel_index?: NUMt = new NumInfo('which item index the carousel viewer is showing'); - _label_minFontSize?: NUMt = new NumInfo('minimum font size for labelBoxes'); - _label_maxFontSize?: NUMt = new NumInfo('maximum font size for labelBoxes'); - stroke_width?: NUMt = new NumInfo('width of an ink stroke'); - icon_label?: STRt = new StrInfo('label to use for a fontIcon doc (otherwise, the title is used)'); - mediaState?: STRt = new StrInfo('status of audio/video media document: "pendingRecording", "recording", "paused", "playing"'); + _label_minFontSize?: NUMt = new NumInfo('minimum font size for labelBoxes', false); + _label_maxFontSize?: NUMt = new NumInfo('maximum font size for labelBoxes', false); + stroke_width?: NUMt = new NumInfo('width of an ink stroke', false); + icon_label?: STRt = new StrInfo('label to use for a fontIcon doc (otherwise, the title is used)', false); + mediaState?: STRt = new StrInfo('status of audio/video media document: "pendingRecording", "recording", "paused", "playing"', false); recording?: BOOLt = new BoolInfo('whether WebCam is recording or not'); autoPlayAnchors?: BOOLt = new BoolInfo('whether to play audio/video when an anchor is clicked in a stackedTimeline.'); dontPlayLinkOnSelect?: BOOLt = new BoolInfo('whether an audio/video should start playing when a link is followed to it.'); @@ -270,7 +281,7 @@ export class DocumentOptions { contextMenuIcons?: List; childFilters_boolean?: string; childFilters?: List; - childLimitHeight?: NUMt = new NumInfo('whether to limit the height of collection children. 0 - means height can be no bigger than width'); + childLimitHeight?: NUMt = new NumInfo('whether to limit the height of collection children. 0 - means height can be no bigger than width', false); childLayoutTemplate?: Doc; // template for collection to use to render its children (see PresBox layout in tree view) childLayoutString?: string; // template string for collection to use to render its children childDocumentsActive?: BOOLt = new BoolInfo('whether child documents are active when parent is document active'); @@ -282,12 +293,12 @@ export class DocumentOptions { childContextMenuIcons?: List; targetScriptKey?: string; // where to write a template script (used by collections with click templates which need to target onClick, onDoubleClick, etc) - lastFrame?: NUMt = new NumInfo('the last frame of a frame-based collection (e.g., progressive slide)'); - activeFrame?: NUMt = new NumInfo('the active frame of a document in a frame base collection'); - appearFrame?: NUMt = new NumInfo('the frame in which the document appears'); - _currentFrame?: NUMt = new NumInfo('the current frame of a frame-based collection (e.g., progressive slide)'); + lastFrame?: NUMt = new NumInfo('the last frame of a frame-based collection (e.g., progressive slide)', false); + activeFrame?: NUMt = new NumInfo('the active frame of a document in a frame base collection', false); + appearFrame?: NUMt = new NumInfo('the frame in which the document appears', false); + _currentFrame?: NUMt = new NumInfo('the current frame of a frame-based collection (e.g., progressive slide)', false); - isSystem?: BOOLt = new BoolInfo('is this a system created/owned doc', true); + isSystem?: BOOLt = new BoolInfo('is this a system created/owned doc', false); isBaseProto?: BOOLt = new BoolInfo('is doc a base level prototype for data documents as opposed to data documents which are prototypes for layout documents. base protos are not cloned during a deep'); isTemplateForField?: string; // the field key for which the containing document is a rendering template isTemplateDoc?: BOOLt = new BoolInfo('is the document a template for creating other documents'); @@ -296,21 +307,23 @@ export class DocumentOptions { _isTimelineLabel?: BOOLt = new BoolInfo('is document a timeline label'); _isLightbox?: BOOLt = new BoolInfo('whether a collection acts as a lightbox by opening lightbox links by hiding all other documents in collection besides link target'); - presPanX?: NUMt = new NumInfo('panX saved as a view spec'); - presPanY?: NUMt = new NumInfo('panY saved as a view spec'); - presViewScale?: NUMt = new NumInfo('viewScale saved as a view Spec'); - presTransition?: NUMt = new NumInfo('the time taken for the transition TO a document'); - presDuration?: NUMt = new NumInfo('the duration of the slide in presentation view'); + presPanX?: NUMt = new NumInfo('panX saved as a view spec', false); + presPanY?: NUMt = new NumInfo('panY saved as a view spec', false); + presViewScale?: NUMt = new NumInfo('viewScale saved as a view Spec', false); + presTransition?: NUMt = new NumInfo('the time taken for the transition TO a document', false); + presDuration?: NUMt = new NumInfo('the duration of the slide in presentation view', false); presZoomText?: BOOLt = new BoolInfo('whether text anchors should shown in a larger box when following links to make them stand out'); data?: any; data_useCors?: BOOLt = new BoolInfo('whether CORS protocol should be used for web page'); columnHeaders?: List; // headers for stacking views schemaHeaders?: List; // headers for schema view - dockingConfig?: STRt = new StrInfo('configuration of golden layout windows (applies only if doc is rendered as a CollectionDockingView)'); + dockingConfig?: STRt = new StrInfo('configuration of golden layout windows (applies only if doc is rendered as a CollectionDockingView)', false); icon?: string; // icon used by fonticonbox to render button noteType?: string; + // STOPPING HERE + // freeform properties _freeform_backgroundGrid?: boolean; _freeform_scale?: NUMt = new NumInfo('how much a freeform view has been scaled (zoomed)'); @@ -380,7 +393,7 @@ export class DocumentOptions { cloneFieldFilter?: List; // fields not to copy when the document is clonedclipboard?: Doc; dragWhenActive?: BOOLt = new BoolInfo('should document drag when it is active - e.g., pileView, group'); dragAction?: DROPt = new DAInfo('how to drag document when it is active (e.g., tree, groups)'); - dragFactory_count?: NUMt = new NumInfo('number of items created from a drag button (used for setting title with incrementing index)', true); + dragFactory_count?: NUMt = new NumInfo('number of items created from a drag button (used for setting title with incrementing index)', false, true); dragFactory?: Doc; // document to create when dragging with a suitable onDragStart script clickFactory?: Doc; // document to create when clicking on a button with a suitable onClick script onDragStart?: ScriptField; //script to execute at start of drag operation -- e.g., when a "creator" button is dragged this script generates a different document to drop diff --git a/src/client/util/.ClientUtils.ts.icloud b/src/client/util/.ClientUtils.ts.icloud deleted file mode 100644 index e5e477586..000000000 Binary files a/src/client/util/.ClientUtils.ts.icloud and /dev/null differ diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 1a923a995..93f4cf818 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -15,7 +15,8 @@ import { AiOutlineMinusSquare, AiOutlinePlusSquare } from 'react-icons/ai'; import { CiCircleRemove } from 'react-icons/ci'; import { Slider, Rail, Handles, Tracks, Ticks } from 'react-compound-slider'; import { TooltipRail, Handle, Tick, Track } from './nodes/SliderBox-components'; -import { DocumentOptions } from '../documents/Documents'; +import { DocumentOptions, FInfo } from '../documents/Documents'; +import { string32 } from 'pdfjs-dist/types/src/shared/util'; //slight bug when you don't click on background canvas before creating filter and the you click on the canvas @@ -28,6 +29,8 @@ interface filterProps { @observer export class FilterPanel extends React.Component { + private _documentOptions: DocumentOptions = new DocumentOptions(); + public static LayoutString(fieldKey: string) { return FieldView.LayoutString(FilterPanel, fieldKey); } @@ -262,12 +265,21 @@ export class FilterPanel extends React.Component { render() { // console.log('this is frist one today ' + this._allFacets); this._allFacets.forEach(element => console.log(element)); - const options = this._allFacets.filter(facet => this.activeFacetHeaders.indexOf(facet) === -1).map(facet => ({ value: facet, label: facet })); + // const options = Object.entries(this._documentOptions).forEach((pair: [string, FInfo]) => pair[1].filterable ).map(facet => value: facet, label: facet) //this._allFacets.filter(facet => this.activeFacetHeaders.indexOf(facet) === -1).map(facet => ({ value: facet, label: facet })); // console.log('HEELLLLLL ' + DocumentOptions); - const freeformOptions: DocumentOptions = {}; + let filteredOptions: string[] = ['author', 'tags', 'text', 'acl-Guest']; + + Object.entries(this._documentOptions).forEach((pair: [string, FInfo]) => { + if (pair[1].filterable) { + filteredOptions.push(pair[0]); + console.log('THIS IS FILTERABLE ALKDJFIIEII' + filteredOptions); + } + }); + + let options = filteredOptions.map(facet => ({ value: facet, label: facet })); - console.log('wht is this ' + freeformOptions.author); + // Object.entries(this._documentOptions).forEach((pair: [string, FInfo]) => console.log('this is first piar ' + pair[0] + ' this is second piar ' + pair[1].filterable)); return (
@@ -373,13 +385,21 @@ export class FilterPanel extends React.Component { case 'range': const domain = renderInfoDomain; + const range = renderInfoRange; + + if (range) { + console.log('this is info range ' + range[0] + ' , ' + range[1]); + } + if (domain) { + console.log('this is info domain ' + domain[0] + ', ' + domain[1]); + return (
Doc.setDocRangeFilter(this.targetDoc, facetHeader, values)} values={renderInfoRange!}> -- cgit v1.2.3-70-g09d2 From 68ddebab45946697270c5f291ff9fdd044b6e83d Mon Sep 17 00:00:00 2001 From: eperelm2 Date: Fri, 25 Aug 2023 17:25:22 +0200 Subject: filter - finishing up --- src/client/views/FilterPanel.scss | 8 ++++---- src/client/views/FilterPanel.tsx | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/views/FilterPanel.scss b/src/client/views/FilterPanel.scss index 421bce6d6..d6d2956aa 100644 --- a/src/client/views/FilterPanel.scss +++ b/src/client/views/FilterPanel.scss @@ -223,10 +223,10 @@ font-weight: bold; } -// .sliderBox-outerDiv { -// display: flex; -// align-items: center; -// } +.sliderBox-outerDiv { + display: inline-block; + vertical-align: middle; +} // .sliderBox-outerDiv { // width: 30%;// width: calc(100% - 14px); // 14px accounts for handles that are at the max value of the slider that would extend outside the box diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index f1eeb6fa7..11c2fc86c 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -392,9 +392,11 @@ export class FilterPanel extends React.Component { return ( <> -
- {/* console.log('on change'))} /> */} + {/*
+ console.log('on change'))} /> +
*/} +
Date: Sun, 27 Aug 2023 20:25:55 -0400 Subject: lots of cleanup to streamline import orderings (ie packages should not mutually import each other directly or via a chain). change raiseWhenDragged to be keepZWhenDragged and got rid of system wide default. --- src/Utils.ts | 2 +- src/client/DocServer.ts | 15 ++- src/client/apis/youtube/YoutubeBox.tsx | 6 +- src/client/documents/Documents.ts | 10 +- src/client/util/CurrentUserUtils.ts | 11 +- src/client/util/DictationManager.ts | 2 +- src/client/util/DocumentManager.ts | 22 +++- src/client/util/DragManager.ts | 21 +--- src/client/util/DropConverter.ts | 14 +-- src/client/util/GroupManager.tsx | 4 +- src/client/util/GroupMemberView.tsx | 2 +- src/client/util/SearchUtil.ts | 104 ++++++++++++++- src/client/util/SettingsManager.tsx | 89 ++++++------- src/client/util/SharingManager.tsx | 10 +- src/client/util/reportManager/ReportManager.tsx | 4 +- src/client/views/ContextMenuItem.tsx | 6 +- src/client/views/DocumentDecorations.tsx | 11 +- src/client/views/EditableView.tsx | 1 - src/client/views/FilterPanel.tsx | 23 ++-- src/client/views/LightboxView.tsx | 11 +- src/client/views/Main.tsx | 6 +- src/client/views/MainView.tsx | 38 +++--- src/client/views/PropertiesView.tsx | 20 +-- src/client/views/SidebarAnnos.tsx | 4 +- src/client/views/StyleProvider.tsx | 15 ++- src/client/views/UndoStack.tsx | 2 +- .../views/collections/CollectionDockingView.tsx | 4 +- src/client/views/collections/CollectionMenu.tsx | 2 +- .../collections/CollectionStackedTimeline.tsx | 4 +- src/client/views/collections/TabDocView.tsx | 13 +- src/client/views/collections/TreeSort.ts | 6 + src/client/views/collections/TreeView.tsx | 11 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 4 +- src/client/views/linking/LinkPopup.tsx | 3 +- .../views/newlightbox/ButtonMenu/ButtonMenu.tsx | 19 ++- src/client/views/newlightbox/NewLightboxView.tsx | 139 ++++++++++----------- src/client/views/nodes/DocumentView.tsx | 16 ++- src/client/views/nodes/FontIconBox/FontIconBox.tsx | 17 +-- src/client/views/nodes/LinkDocPreview.tsx | 6 +- src/client/views/nodes/LoadingBox.tsx | 6 +- src/client/views/nodes/ScreenshotBox.tsx | 6 +- src/client/views/nodes/VideoBox.tsx | 5 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 24 ++-- .../views/nodes/generativeFill/GenerativeFill.tsx | 33 +++-- src/client/views/nodes/trails/PresBox.tsx | 4 +- src/client/views/pdf/AnchorMenu.tsx | 15 +-- src/client/views/search/IconBar.tsx | 28 +++-- src/client/views/search/SearchBox.tsx | 110 +--------------- src/client/views/topbar/TopBar.tsx | 16 ++- src/client/views/webcam/DashWebRTCVideo.tsx | 6 +- src/fields/Doc.ts | 26 +++- src/fields/RichTextUtils.ts | 10 +- 52 files changed, 492 insertions(+), 494 deletions(-) create mode 100644 src/client/views/collections/TreeSort.ts (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/Utils.ts b/src/Utils.ts index 7f83ab8f5..9a94694a2 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -3,10 +3,10 @@ import v5 = require('uuid/v5'); import { ColorState } from 'react-color'; import * as rp from 'request-promise'; import { Socket } from 'socket.io'; +import { DocumentType } from './client/documents/DocumentTypes'; import { Colors } from './client/views/global/globalEnums'; import { Message } from './server/Message'; import Color = require('color'); -import { DocumentType } from './client/documents/DocumentTypes'; export namespace Utils { export let CLICK_TIME = 300; diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index 53c7b857a..5fdea131b 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -1,6 +1,5 @@ import { runInAction } from 'mobx'; import * as rp from 'request-promise'; -import * as io from 'socket.io-client'; import { Doc, DocListCast, Opt } from '../fields/Doc'; import { UpdatingFromServer } from '../fields/DocSymbols'; import { FieldLoader } from '../fields/FieldLoader'; @@ -8,13 +7,13 @@ import { HandleUpdate, Id, Parent } from '../fields/FieldSymbols'; import { ObjectField } from '../fields/ObjectField'; import { RefField } from '../fields/RefField'; import { DocCast, StrCast } from '../fields/Types'; -import MobileInkOverlay from '../mobile/MobileInkOverlay'; +//import MobileInkOverlay from '../mobile/MobileInkOverlay'; import { emptyFunction, Utils } from '../Utils'; import { GestureContent, MessageStore, MobileDocumentUploadContent, MobileInkOverlayContent, UpdateMobileInkOverlayPositionContent, YoutubeQueryTypes } from './../server/Message'; import { DocumentType } from './documents/DocumentTypes'; import { LinkManager } from './util/LinkManager'; import { SerializationHelper } from './util/SerializationHelper'; -import { GestureOverlay } from './views/GestureOverlay'; +//import { GestureOverlay } from './views/GestureOverlay'; /** * This class encapsulates the transfer and cross-client synchronization of @@ -189,17 +188,17 @@ export namespace DocServer { // mobile ink overlay socket events to communicate between mobile view and desktop view _socket.addEventListener('receiveGesturePoints', (content: GestureContent) => { - MobileInkOverlay.Instance.drawStroke(content); + // MobileInkOverlay.Instance.drawStroke(content); }); _socket.addEventListener('receiveOverlayTrigger', (content: MobileInkOverlayContent) => { - GestureOverlay.Instance.enableMobileInkOverlay(content); - MobileInkOverlay.Instance.initMobileInkOverlay(content); + //GestureOverlay.Instance.enableMobileInkOverlay(content); + // MobileInkOverlay.Instance.initMobileInkOverlay(content); }); _socket.addEventListener('receiveUpdateOverlayPosition', (content: UpdateMobileInkOverlayPositionContent) => { - MobileInkOverlay.Instance.updatePosition(content); + // MobileInkOverlay.Instance.updatePosition(content); }); _socket.addEventListener('receiveMobileDocumentUpload', (content: MobileDocumentUploadContent) => { - MobileInkOverlay.Instance.uploadDocument(content); + // MobileInkOverlay.Instance.uploadDocument(content); }); } diff --git a/src/client/apis/youtube/YoutubeBox.tsx b/src/client/apis/youtube/YoutubeBox.tsx index 05879a247..2da9927c0 100644 --- a/src/client/apis/youtube/YoutubeBox.tsx +++ b/src/client/apis/youtube/YoutubeBox.tsx @@ -6,7 +6,7 @@ import { Cast, NumCast, StrCast } from '../../../fields/Types'; import { Utils } from '../../../Utils'; import { DocServer } from '../../DocServer'; import { Docs } from '../../documents/Documents'; -import { DocumentDecorations } from '../../views/DocumentDecorations'; +import { DocumentView } from '../../views/nodes/DocumentView'; import { FieldView, FieldViewProps } from '../../views/nodes/FieldView'; import '../../views/nodes/WebBox.scss'; import './YoutubeBox.scss'; @@ -355,9 +355,9 @@ export class YoutubeBox extends React.Component {
); - const frozen = !this.props.isSelected() || DocumentDecorations.Instance.Interacting; + const frozen = !this.props.isSelected() || DocumentView.Interacting; - const classname = 'webBox-cont' + (this.props.isSelected() && Doc.ActiveTool === InkTool.None && !DocumentDecorations.Instance.Interacting ? '-interactive' : ''); + const classname = 'webBox-cont' + (this.props.isSelected() && Doc.ActiveTool === InkTool.None && !DocumentView.Interacting ? '-interactive' : ''); return ( <>
{content}
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 1186446e1..919958b24 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -19,7 +19,6 @@ import { aggregateBounds, OmitKeys, Utils } from '../../Utils'; import { YoutubeBox } from '../apis/youtube/YoutubeBox'; import { DocServer } from '../DocServer'; import { Networking } from '../Network'; -import { DocumentManager } from '../util/DocumentManager'; import { DragManager, dropActionType } from '../util/DragManager'; import { DirectoryImportBox } from '../util/Import & Export/DirectoryImportBox'; import { FollowLinkScript } from '../util/LinkFollower'; @@ -34,12 +33,12 @@ import { ContextMenuProps } from '../views/ContextMenuItem'; import { DFLT_IMAGE_NATIVE_DIM } from '../views/global/globalCssVariables.scss'; import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, ActiveIsInkMask, InkingStroke } from '../views/InkingStroke'; import { AudioBox } from '../views/nodes/AudioBox'; -import { FontIconBox } from '../views/nodes/FontIconBox/FontIconBox'; import { ColorBox } from '../views/nodes/ColorBox'; import { ComparisonBox } from '../views/nodes/ComparisonBox'; import { DataVizBox } from '../views/nodes/DataVizBox/DataVizBox'; import { EquationBox } from '../views/nodes/EquationBox'; import { FieldViewProps } from '../views/nodes/FieldView'; +import { FontIconBox } from '../views/nodes/FontIconBox/FontIconBox'; import { FormattedTextBox } from '../views/nodes/formattedText/FormattedTextBox'; import { FunctionPlotBox } from '../views/nodes/FunctionPlotBox'; import { ImageBox } from '../views/nodes/ImageBox'; @@ -394,7 +393,7 @@ export class DocumentOptions { onPointerUp?: ScriptField; _forceActive?: BOOLt = new BoolInfo('flag to handle pointer events when not selected (or otherwise active)'); _dragOnlyWithinContainer?: BOOLt = new BoolInfo('whether the document should remain in its collection when someone tries to drag and drop it elsewhere'); - _raiseWhenDragged?: BOOLt = new BoolInfo('whether a document is brought to front when dragged.'); + _keepZWhenDragged?: BOOLt = new BoolInfo('whether a document should keep its z-order when dragged.'); childDragAction?: DROPt = new DAInfo('what should happen to the child documents when they are dragged from the collection'); dropConverter?: ScriptField; // script to run when documents are dropped on this Document. dropAction?: DROPt = new DAInfo("what should happen to this document when it's dropped somewhere else"); @@ -1371,7 +1370,7 @@ export namespace DocUtils { export let ActiveRecordings: { props: FieldViewProps; getAnchor: (addAsAnnotation: boolean) => Doc }[] = []; export function MakeLinkToActiveAudio(getSourceDoc: () => Doc | undefined, broadcastEvent = true) { - broadcastEvent && runInAction(() => (DocumentManager.Instance.RecordingEvent = DocumentManager.Instance.RecordingEvent + 1)); + broadcastEvent && runInAction(() => (Doc.RecordingEvent = Doc.RecordingEvent + 1)); return DocUtils.ActiveRecordings.map(audio => { const sourceDoc = getSourceDoc(); return sourceDoc && DocUtils.MakeLink(sourceDoc, audio.getAnchor(true) || audio.props.Document, { link_displayLine: false, link_relationship: 'recording annotation:linked recording', link_description: 'recording timeline' }); @@ -1380,7 +1379,6 @@ export namespace DocUtils { export function MakeLink(source: Doc, target: Doc, linkSettings: { link_relationship?: string; link_description?: string; link_displayLine?: boolean }, id?: string, showPopup?: number[]) { if (!linkSettings.link_relationship) linkSettings.link_relationship = target.type === DocumentType.RTF ? 'Commentary:Comments On' : 'link'; - const sv = DocumentManager.Instance.getDocumentView(source); if (target.doc === Doc.UserDoc()) return undefined; const makeLink = action((linkDoc: Doc, showPopup?: number[]) => { @@ -1840,8 +1838,6 @@ export namespace DocUtils { } if (overwriteDoc) { Doc.removeCurrentlyLoading(overwriteDoc); - // loading doc icons are just labels. so any icon views of loading docs need to be replaced with the proper icon view. - DocumentManager.Instance.getAllDocumentViews(overwriteDoc).forEach(dv => StrCast(dv.rootDoc.layout_fieldKey) === 'layout_icon' && dv.iconify(() => dv.iconify())); } generatedDocuments.push(doc); } diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index ea995e4af..d52e389d6 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -18,7 +18,6 @@ import { CollectionViewType, DocumentType } from "../documents/DocumentTypes"; import { TreeViewType } from "../views/collections/CollectionTreeView"; import { DashboardView } from "../views/DashboardView"; import { Colors } from "../views/global/globalEnums"; -import { MainView } from "../views/MainView"; import { OpenWhere } from "../views/nodes/DocumentView"; import { ButtonType } from "../views/nodes/FontIconBox/FontIconBox"; import { ImportElementBox } from "../views/nodes/importBox/ImportElementBox"; @@ -621,9 +620,9 @@ export class CurrentUserUtils { static freeTools(): Button[] { return [ - { title: "Bottom", icon: "arrows-down-to-line",toolTip: "Make doc topmost", btnType: ButtonType.ClickButton, expertMode: false, funcs: {}, scripts: { onClick: 'sendToBack()'}}, // Only when floating document is selected in freeform - { title: "Top", icon: "arrows-up-to-line", toolTip: "Make doc bottommost", btnType: ButtonType.ClickButton, expertMode: false, funcs: {}, scripts: { onClick: 'bringToFront()'}}, // Only when floating document is selected in freeform - { title: "Z order", icon: "z", toolTip: "Bring Forward on Drag (double click to set for all)",waitForDoubleClickToClick:true, btnType: ButtonType.ToggleButton, expertMode: false, funcs: {}, scripts: { onClick: 'toggleRaiseOnDrag(false, _readOnly_)', onDoubleClick:`{ return toggleRaiseOnDrag(true, _readOnly_)`}}, // Only when floating document is selected in freeform + { title: "Bottom", icon: "arrows-down-to-line",toolTip: "Make doc topmost", btnType: ButtonType.ClickButton, expertMode: false, funcs: {}, scripts: { onClick: 'sendToBack()'}}, // Only when floating document is selected in freeform + { title: "Top", icon: "arrows-up-to-line", toolTip: "Make doc bottommost", btnType: ButtonType.ClickButton, expertMode: false, funcs: {}, scripts: { onClick: 'bringToFront()'}}, // Only when floating document is selected in freeform + { title: "Z order", icon: "z", toolTip: "Keep Z order on Drag", btnType: ButtonType.ToggleButton, expertMode: false, funcs: {}, scripts: { onClick: '{ return toggleRaiseOnDrag(_readOnly_);}'}}, // Only when floating document is selected in freeform ] } static viewTools(): Button[] { @@ -841,7 +840,6 @@ export class CurrentUserUtils { doc.isSystem ?? (doc.isSystem = true); doc.title ?? (doc.title = Doc.CurrentUserEmail); Doc.noviceMode ?? (Doc.noviceMode = true); - doc._raiseWhenDragged ?? (doc._raiseWhenDragged = true); doc._showLabel ?? (doc._showLabel = true); doc.textAlign ?? (doc.textAlign = "left"); doc.activeTool = InkTool.None; @@ -996,8 +994,5 @@ export class CurrentUserUtils { ScriptingGlobals.add(function MySharedDocs() { return Doc.MySharedDocs; }, "document containing all shared Docs"); ScriptingGlobals.add(function IsNoviceMode() { return Doc.noviceMode; }, "is Dash in novice mode"); ScriptingGlobals.add(function toggleComicMode() { Doc.UserDoc().renderStyle = Doc.UserDoc().renderStyle === "comic" ? undefined : "comic"; }, "switches between comic and normal document rendering"); -ScriptingGlobals.add(function createNewPresentation() { return MainView.Instance.createNewPresentation(); }, "creates a new presentation when called"); -ScriptingGlobals.add(function openPresentation(pres:Doc) { return MainView.Instance.openPresentation(pres); }, "creates a new presentation when called"); -ScriptingGlobals.add(function createNewFolder() { return MainView.Instance.createNewFolder(); }, "creates a new folder in myFiles when called"); ScriptingGlobals.add(function importDocument() { return CurrentUserUtils.importDocument(); }, "imports files from device directly into the import sidebar"); ScriptingGlobals.add(function setInkToolDefaults() { Doc.ActiveTool = InkTool.None; }); \ No newline at end of file diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts index 717473aa1..0fd7e840c 100644 --- a/src/client/util/DictationManager.ts +++ b/src/client/util/DictationManager.ts @@ -11,7 +11,7 @@ import { Utils } from '../../Utils'; import { Docs } from '../documents/Documents'; import { DocumentType } from '../documents/DocumentTypes'; import { DictationOverlay } from '../views/DictationOverlay'; -import { DocumentView, OpenWhere, OpenWhereMod } from '../views/nodes/DocumentView'; +import { DocumentView, OpenWhere } from '../views/nodes/DocumentView'; import { SelectionManager } from './SelectionManager'; import { UndoManager } from './UndoManager'; diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 5b627c2f3..c2827dac7 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -1,4 +1,4 @@ -import { action, computed, observable, ObservableSet } from 'mobx'; +import { action, computed, observable, ObservableSet, observe, reaction } from 'mobx'; import { Doc, DocListCast, Opt } from '../../fields/Doc'; import { AclAdmin, AclEdit, Animation } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; @@ -23,7 +23,6 @@ export class DocumentManager { //global holds all of the nodes (regardless of which collection they're in) @observable _documentViews = new Set(); @observable public LinkAnchorBoxViews: DocumentView[] = []; - @observable public RecordingEvent = 0; @observable public LinkedDocumentViews: { a: DocumentView; b: DocumentView; l: Doc }[] = []; @computed public get DocumentViews() { return Array.from(this._documentViews).filter(view => !(view.ComponentView instanceof KeyValueBox) && (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(view.docViewPath))); @@ -41,7 +40,22 @@ export class DocumentManager { } //private constructor so no other class can create a nodemanager - private constructor() {} + private constructor() { + if (!Doc.CurrentlyLoading) Doc.CurrentlyLoading = []; + observe(Doc.CurrentlyLoading, change => { + // watch CurrentlyLoading-- when something is loaded, it's removed from the list and we have to update its icon if it were iconified since LoadingBox icons are different than the media they become + switch (change.type as any) { + case 'update': + break; + case 'remove': + // DocumentManager.Instance.getAllDocumentViews(change as any).forEach(dv => StrCast(dv.rootDoc.layout_fieldKey) === 'layout_icon' && dv.iconify(() => dv.iconify())); + break; + case 'splice': + (change as any).removed.forEach((doc: Doc) => DocumentManager.Instance.getAllDocumentViews(doc).forEach(dv => StrCast(dv.rootDoc.layout_fieldKey) === 'layout_icon' && dv.iconify(() => dv.iconify()))); + break; + } + }); + } private _viewRenderedCbs: { doc: Doc; func: (dv: DocumentView) => any }[] = []; public AddViewRenderedCb = (doc: Opt, func: (dv: DocumentView) => any) => { @@ -310,7 +324,7 @@ export class DocumentManager { if (viewSpec && docView) { if (docView.ComponentView instanceof FormattedTextBox) docView.ComponentView?.focus(viewSpec, options); PresBox.restoreTargetDocView(docView, viewSpec, options.zoomTime ?? 500); - Doc.linkFollowHighlight(viewSpec ? [docView.rootDoc, viewSpec]: docView.rootDoc, undefined, options.effect); + Doc.linkFollowHighlight(viewSpec ? [docView.rootDoc, viewSpec] : docView.rootDoc, undefined, options.effect); if (options.playAudio) DocumentManager.playAudioAnno(docView.rootDoc); if (options.toggleTarget && (!options.didMove || docView.rootDoc.hidden)) docView.rootDoc.hidden = !docView.rootDoc.hidden; if (options.effect) docView.rootDoc[Animation] = options.effect; diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 489c9df4a..05da5ebed 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -61,12 +61,6 @@ export namespace DragManager { export let StartWindowDrag: Opt<(e: { pageX: number; pageY: number }, dragDocs: Doc[], finishDrag?: (aborted: boolean) => void) => void>; export let CompleteWindowDrag: Opt<(aborted: boolean) => void>; - export function GetRaiseWhenDragged() { - return BoolCast(Doc.UserDoc()._raiseWhenDragged); - } - export function SetRaiseWhenDragged(val: boolean) { - Doc.UserDoc()._raiseWhenDragged = val; - } export function Root() { const root = document.getElementById('root'); if (!root) { @@ -605,18 +599,9 @@ export namespace DragManager { } } -ScriptingGlobals.add(function toggleRaiseOnDrag(forAllDocs: boolean, readOnly?: boolean) { +ScriptingGlobals.add(function toggleRaiseOnDrag(readOnly?: boolean) { if (readOnly) { - if (SelectionManager.Views().length) - return SelectionManager.Views().some(dv => dv.rootDoc.raiseWhenDragged) - ? Colors.MEDIUM_BLUE - : SelectionManager.Views().some(dv => dv.rootDoc.raiseWhenDragged === false) - ? 'transparent' - : DragManager.GetRaiseWhenDragged() - ? Colors.MEDIUM_BLUE_ALT - : Colors.LIGHT_BLUE; - return DragManager.GetRaiseWhenDragged() ? Colors.MEDIUM_BLUE_ALT : 'transparent'; + return SelectionManager.Views().some(dv => dv.rootDoc.keepZWhenDragged); } - if (!forAllDocs) SelectionManager.Views().map(dv => (dv.rootDoc.raiseWhenDragged ? (dv.rootDoc.raiseWhenDragged = undefined) : dv.rootDoc.raiseWhenDragged === false ? (dv.rootDoc.raiseWhenDragged = true) : (dv.rootDoc.raiseWhenDragged = false))); - else DragManager.SetRaiseWhenDragged(!DragManager.GetRaiseWhenDragged()); + SelectionManager.Views().map(dv => (dv.rootDoc.keepZWhenDragged = !dv.rootDoc.keepZWhenDragged)); }); diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts index f235be192..dbdf580cd 100644 --- a/src/client/util/DropConverter.ts +++ b/src/client/util/DropConverter.ts @@ -1,15 +1,15 @@ -import { DragManager } from './DragManager'; import { Doc, DocListCast, Opt } from '../../fields/Doc'; -import { DocumentType } from '../documents/DocumentTypes'; import { ObjectField } from '../../fields/ObjectField'; -import { StrCast, Cast } from '../../fields/Types'; -import { Docs } from '../documents/Documents'; -import { ScriptField, ComputedField } from '../../fields/ScriptField'; import { RichTextField } from '../../fields/RichTextField'; -import { ImageField } from '../../fields/URLField'; -import { ScriptingGlobals } from './ScriptingGlobals'; import { listSpec } from '../../fields/Schema'; +import { ScriptField } from '../../fields/ScriptField'; +import { Cast, StrCast } from '../../fields/Types'; +import { ImageField } from '../../fields/URLField'; +import { Docs } from '../documents/Documents'; +import { DocumentType } from '../documents/DocumentTypes'; import { ButtonType } from '../views/nodes/FontIconBox/FontIconBox'; +import { DragManager } from './DragManager'; +import { ScriptingGlobals } from './ScriptingGlobals'; export function MakeTemplate(doc: Doc, first: boolean = true, rename: Opt = undefined, templateField: string = '') { if (templateField) Doc.GetProto(doc).title = templateField; /// the title determines which field is being templated diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx index c79894032..8973306bf 100644 --- a/src/client/util/GroupManager.tsx +++ b/src/client/util/GroupManager.tsx @@ -282,7 +282,7 @@ export class GroupManager extends React.Component<{}> { */ private get groupCreationModal() { const contents = ( -
+

New Group @@ -367,7 +367,7 @@ export class GroupManager extends React.Component<{}> { const groups = this.groupSort === 'ascending' ? this.allGroups.sort(sortGroups) : this.groupSort === 'descending' ? this.allGroups.sort(sortGroups).reverse() : this.allGroups; return ( -

+
{this.groupCreationModal} {this.currentGroup ? (this.currentGroup = undefined))} /> : null}
diff --git a/src/client/util/GroupMemberView.tsx b/src/client/util/GroupMemberView.tsx index 535d8ccc2..7de0f336f 100644 --- a/src/client/util/GroupMemberView.tsx +++ b/src/client/util/GroupMemberView.tsx @@ -29,7 +29,7 @@ export class GroupMemberView extends React.Component { const hasEditAccess = GroupManager.Instance.hasEditAccess(this.props.group); return !this.props.group ? null : ( -
+
, query: string) { + const blockedTypes = [DocumentType.PRESELEMENT, DocumentType.CONFIG, DocumentType.KVP, DocumentType.FONTICON, DocumentType.BUTTON, DocumentType.SCRIPTING]; + const blockedKeys = [ + 'x', + 'y', + 'proto', + 'width', + 'layout_autoHeight', + 'acl-Override', + 'acl-Guest', + 'embedContainer', + 'zIndex', + 'height', + 'text_scrollHeight', + 'text_height', + 'cloneFieldFilter', + 'isDataDoc', + 'text_annotations', + 'dragFactory_count', + 'text_noTemplate', + 'proto_embeddings', + 'isSystem', + 'layout_fieldKey', + 'isBaseProto', + 'xMargin', + 'yMargin', + 'links', + 'layout', + 'layout_keyValue', + 'layout_fitWidth', + 'type_collection', + 'title_custom', + 'freeform_panX', + 'freeform_panY', + 'freeform_scale', + ]; + query = query.toLowerCase(); + + const results = new Map(); + if (rootDoc) { + const docs = DocListCast(rootDoc[Doc.LayoutFieldKey(rootDoc)]); + const docIDs: String[] = []; + SearchUtil.foreachRecursiveDoc(docs, (depth: number, doc: Doc) => { + const dtype = StrCast(doc.type) as DocumentType; + if (dtype && !blockedTypes.includes(dtype) && !docIDs.includes(doc[Id]) && depth >= 0) { + const hlights = new Set(); + SearchUtil.documentKeys(doc).forEach( + key => + Field.toString(doc[key] as Field) + .toLowerCase() + .includes(query) && hlights.add(key) + ); + blockedKeys.forEach(key => hlights.delete(key)); + + if (Array.from(hlights.keys()).length > 0) { + results.set(doc, Array.from(hlights.keys())); + } + } + docIDs.push(doc[Id]); + }); + } + return results; + } + /** + * @param {Doc} doc - doc for which keys are returned + * + * This method returns a list of a document doc's keys. + */ + export function documentKeys(doc: Doc) { + const keys: { [key: string]: boolean } = {}; + Doc.GetAllPrototypes(doc).map(proto => Object.keys(proto).forEach(key => (keys[key] = false))); + return Array.from(Object.keys(keys)); + } + + /** + * @param {Doc[]} docs - docs to be searched through recursively + * @param {number, Doc => void} func - function to be called on each doc + * + * This method iterates through an array of docs and all docs within those docs, calling + * the function func on each doc. + */ + export function foreachRecursiveDoc(docs: Doc[], func: (depth: number, doc: Doc) => void) { + let newarray: Doc[] = []; + var depth = 0; + const visited: Doc[] = []; + while (docs.length > 0) { + newarray = []; + docs.filter(d => d && !visited.includes(d)).forEach(d => { + visited.push(d); + const fieldKey = Doc.LayoutFieldKey(d); + const annos = !Field.toString(Doc.LayoutField(d) as Field).includes('CollectionView'); + const data = d[annos ? fieldKey + '_annotations' : fieldKey]; + data && newarray.push(...DocListCast(data)); + const sidebar = d[fieldKey + '_sidebar']; + sidebar && newarray.push(...DocListCast(sidebar)); + func(depth, d); + }); + docs = newarray; + depth++; + } + } export interface IdSearchResult { ids: string[]; lines: string[][]; diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index bb370e1a4..720badd40 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -13,7 +13,6 @@ import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager import { DocServer } from '../DocServer'; import { Networking } from '../Network'; import { MainViewModal } from '../views/MainViewModal'; -import { FontIconBox } from '../views/nodes/FontIconBox/FontIconBox'; import { GroupManager } from './GroupManager'; import './SettingsManager.scss'; import { undoBatch } from './UndoManager'; @@ -67,15 +66,15 @@ export class SettingsManager extends React.Component<{}> { } }; - @computed get userColor() { + @computed public static get userColor() { return StrCast(Doc.UserDoc().userColor); } - @computed get userVariantColor() { + @computed public static get userVariantColor() { return StrCast(Doc.UserDoc().userVariantColor); } - @computed get userBackgroundColor() { + @computed public static get userBackgroundColor() { return StrCast(Doc.UserDoc().userBackgroundColor); } @@ -150,35 +149,35 @@ export class SettingsManager extends React.Component<{}> { val: scheme, }))} dropdownType={DropdownType.SELECT} - color={this.userColor} + color={SettingsManager.userColor} fillWidth /> {userTheme === ColorScheme.Custom && ( } - selectedColor={this.userColor} + selectedColor={SettingsManager.userColor} setSelectedColor={this.switchUserColor} setFinalColor={this.switchUserColor} /> } - selectedColor={this.userBackgroundColor} + selectedColor={SettingsManager.userBackgroundColor} setSelectedColor={this.switchUserBackgroundColor} setFinalColor={this.switchUserBackgroundColor} /> } - selectedColor={this.userVariantColor} + selectedColor={SettingsManager.userVariantColor} setSelectedColor={this.switchUserVariantColor} setFinalColor={this.switchUserVariantColor} /> @@ -198,7 +197,7 @@ export class SettingsManager extends React.Component<{}> { onClick={e => (Doc.UserDoc().layout_showTitle = Doc.UserDoc().layout_showTitle ? undefined : 'author_date')} toggleStatus={Doc.UserDoc().layout_showTitle !== undefined} size={Size.XSMALL} - color={this.userColor} + color={SettingsManager.userColor} /> { onClick={e => (Doc.UserDoc()['documentLinksButton-fullMenu'] = !Doc.UserDoc()['documentLinksButton-fullMenu'])} toggleStatus={BoolCast(Doc.UserDoc()['documentLinksButton-fullMenu'])} size={Size.XSMALL} - color={this.userColor} + color={SettingsManager.userColor} /> FontIconBox.SetShowLabels(!FontIconBox.GetShowLabels())} - toggleStatus={FontIconBox.GetShowLabels()} + onClick={e => Doc.SetShowIconLabels(!Doc.GetShowIconLabels())} + toggleStatus={Doc.GetShowIconLabels()} size={Size.XSMALL} - color={this.userColor} + color={SettingsManager.userColor} /> FontIconBox.SetRecognizeGestures(!FontIconBox.GetRecognizeGestures())} - toggleStatus={FontIconBox.GetRecognizeGestures()} + onClick={e => Doc.SetRecognizeGestures(!Doc.GetRecognizeGestures())} + toggleStatus={Doc.GetRecognizeGestures()} size={Size.XSMALL} - color={this.userColor} + color={SettingsManager.userColor} /> { onClick={e => (Doc.UserDoc().activeInkHideTextLabels = !Doc.UserDoc().activeInkHideTextLabels)} toggleStatus={BoolCast(Doc.UserDoc().activeInkHideTextLabels)} size={Size.XSMALL} - color={this.userColor} + color={SettingsManager.userColor} /> { onClick={e => (Doc.UserDoc().openInkInLightbox = !Doc.UserDoc().openInkInLightbox)} toggleStatus={BoolCast(Doc.UserDoc().openInkInLightbox)} size={Size.XSMALL} - color={this.userColor} + color={SettingsManager.userColor} /> { onClick={e => (Doc.UserDoc().showLinkLines = !Doc.UserDoc().showLinkLines)} toggleStatus={BoolCast(Doc.UserDoc().showLinkLines)} size={Size.XSMALL} - color={this.userColor} + color={SettingsManager.userColor} />
); @@ -284,7 +283,7 @@ export class SettingsManager extends React.Component<{}> {
{/* */} - {}} /> + {}} /> { return { @@ -301,7 +300,7 @@ export class SettingsManager extends React.Component<{}> { setSelectedVal={val => { this.changeFontFamily(val as string); }} - color={this.userColor} + color={SettingsManager.userColor} fillWidth /> @@ -329,12 +328,12 @@ export class SettingsManager extends React.Component<{}> { @computed get passwordContent() { return (
- this.changeVal(val as string, 'curr')} fillWidth password /> - this.changeVal(val as string, 'new')} fillWidth password /> - this.changeVal(val as string, 'conf')} fillWidth password /> + this.changeVal(val as string, 'curr')} fillWidth password /> + this.changeVal(val as string, 'new')} fillWidth password /> + this.changeVal(val as string, 'conf')} fillWidth password /> {!this.passwordResultText ? null :
{this.passwordResultText}
} -
); } @@ -394,10 +393,10 @@ export class SettingsManager extends React.Component<{}> { dropdownType={DropdownType.SELECT} type={Type.TERT} placement="bottom-start" - color={this.userColor} + color={SettingsManager.userColor} fillWidth /> - +
Freeform Navigation @@ -422,15 +421,21 @@ export class SettingsManager extends React.Component<{}> { dropdownType={DropdownType.SELECT} type={Type.TERT} placement="bottom-start" - color={this.userColor} + color={SettingsManager.userColor} />
Permissions
-
@@ -449,7 +454,7 @@ export class SettingsManager extends React.Component<{}> { ]; return (
-
+
{tabs.map(tab => { const isActive = this.activeTab === tab.title; @@ -457,8 +462,8 @@ export class SettingsManager extends React.Component<{}> {
(this.activeTab = tab.title))}> @@ -469,19 +474,19 @@ export class SettingsManager extends React.Component<{}> {
-
{DashVersion}
-
+
{DashVersion}
+
{Doc.CurrentUserEmail}
-
-
-
+
{tabs.map(tab => (
{tab.ele} diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 81ddeb9e3..9a9097bf7 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -18,10 +18,10 @@ import { DictationOverlay } from '../views/DictationOverlay'; import { MainViewModal } from '../views/MainViewModal'; import { DocumentView } from '../views/nodes/DocumentView'; import { TaskCompletionBox } from '../views/nodes/TaskCompletedBox'; -import { SearchBox } from '../views/search/SearchBox'; import { DocumentManager } from './DocumentManager'; import { GroupManager, UserOptions } from './GroupManager'; import { GroupMemberView } from './GroupMemberView'; +import { SearchUtil } from './SearchUtil'; import { SelectionManager } from './SelectionManager'; import { SettingsManager } from './SettingsManager'; import './SharingManager.scss'; @@ -446,7 +446,7 @@ export class SharingManager extends React.Component<{}> { if (this.myDocAcls) { const newDocs: Doc[] = []; - SearchBox.foreachRecursiveDoc(docs, (depth, doc) => newDocs.push(doc)); + SearchUtil.foreachRecursiveDoc(docs, (depth, doc) => newDocs.push(doc)); docs = newDocs.filter(doc => GetEffectiveAcl(doc) === AclAdmin); } @@ -527,10 +527,10 @@ export class SharingManager extends React.Component<{}> { const permissions = uniform ? StrCast(targetDoc?.[groupKey]) : '-multiple-'; return !permissions ? null : ( -
+
{StrCast(group.title)}
  - {group instanceof Doc ? } size={Size.XSMALL} color={SettingsManager.Instance.userColor} onClick={action(() => (GroupManager.Instance.currentGroup = group))} /> : null} + {group instanceof Doc ? } size={Size.XSMALL} color={SettingsManager.userColor} onClick={action(() => (GroupManager.Instance.currentGroup = group))} /> : null}
{admin || this.myDocAcls ? ( diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx index c194ede32..a2f9de9ab 100644 --- a/src/client/views/topbar/TopBar.tsx +++ b/src/client/views/topbar/TopBar.tsx @@ -1,13 +1,14 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { Button, IconButton, Size, Type, isDark } from 'browndash-components'; +import { Button, IconButton, isDark, Size, Type } from 'browndash-components'; import { action, computed, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { FaBug, FaCamera, FaStamp } from 'react-icons/fa'; +import { FaBug, FaCamera } from 'react-icons/fa'; import { Doc, DocListCast } from '../../../fields/Doc'; import { AclAdmin, DashVersion } from '../../../fields/DocSymbols'; import { StrCast } from '../../../fields/Types'; import { GetEffectiveAcl } from '../../../fields/util'; +import { CurrentUserUtils } from '../../util/CurrentUserUtils'; import { DocumentManager } from '../../util/DocumentManager'; import { PingManager } from '../../util/PingManager'; import { ReportManager } from '../../util/reportManager/ReportManager'; @@ -15,13 +16,12 @@ import { ServerStats } from '../../util/ServerStats'; import { SettingsManager } from '../../util/SettingsManager'; import { SharingManager } from '../../util/SharingManager'; import { UndoManager } from '../../util/UndoManager'; +import { CollectionDockingView } from '../collections/CollectionDockingView'; import { ContextMenu } from '../ContextMenu'; import { DashboardView } from '../DashboardView'; -import { MainView } from '../MainView'; -import { CollectionDockingView } from '../collections/CollectionDockingView'; import { Colors } from '../global/globalEnums'; +import { DocumentView } from '../nodes/DocumentView'; import './TopBar.scss'; -import { CurrentUserUtils } from '../../util/CurrentUserUtils'; /** * ABOUT: This is the topbar in Dash, which included the current Dashboard as well as access to information on the user @@ -43,7 +43,7 @@ export class TopBar extends React.Component { return StrCast(Doc.UserDoc().userVariantColor, Colors.MEDIUM_BLUE); } @computed get backgroundColor() { - return PingManager.Instance.IsBeating ? SettingsManager.Instance.userBackgroundColor : Colors.MEDIUM_GRAY; + return PingManager.Instance.IsBeating ? SettingsManager.userBackgroundColor : Colors.MEDIUM_GRAY; } @observable happyHeart: boolean = PingManager.Instance.IsBeating; @@ -76,9 +76,7 @@ export class TopBar extends React.Component { dash
)} - {Doc.ActiveDashboard && ( -
); } diff --git a/src/client/views/webcam/DashWebRTCVideo.tsx b/src/client/views/webcam/DashWebRTCVideo.tsx index 02e44a793..524492226 100644 --- a/src/client/views/webcam/DashWebRTCVideo.tsx +++ b/src/client/views/webcam/DashWebRTCVideo.tsx @@ -6,8 +6,8 @@ import { observer } from 'mobx-react'; import { Doc } from '../../../fields/Doc'; import { InkTool } from '../../../fields/InkField'; import '../../views/nodes/WebBox.scss'; -import { DocumentDecorations } from '../DocumentDecorations'; import { CollectionFreeFormDocumentViewProps } from '../nodes/CollectionFreeFormDocumentView'; +import { DocumentView } from '../nodes/DocumentView'; import { FieldView, FieldViewProps } from '../nodes/FieldView'; import './DashWebRTCVideo.scss'; import { hangup, initialize, refreshVideos } from './WebCamLogic'; @@ -71,8 +71,8 @@ export class DashWebRTCVideo extends React.Component ); - const frozen = !this.props.isSelected() || DocumentDecorations.Instance.Interacting; - const classname = 'webBox-cont' + (this.props.isSelected() && Doc.ActiveTool === InkTool.None && !DocumentDecorations.Instance.Interacting ? '-interactive' : ''); + const frozen = !this.props.isSelected() || DocumentView.Interacting; + const classname = 'webBox-cont' + (this.props.isSelected() && Doc.ActiveTool === InkTool.None && !DocumentView.Interacting ? '-interactive' : ''); return ( <> diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 4ad38e7fc..f17e10d9e 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -47,7 +47,7 @@ import { FieldId, RefField } from './RefField'; import { RichTextField } from './RichTextField'; import { listSpec } from './Schema'; import { ComputedField, ScriptField } from './ScriptField'; -import { Cast, DocCast, FieldValue, NumCast, StrCast, ToConstructor } from './Types'; +import { BoolCast, Cast, DocCast, FieldValue, NumCast, StrCast, ToConstructor } from './Types'; import { AudioField, CsvField, ImageField, PdfField, VideoField, WebField } from './URLField'; import { containedFieldChangedHandler, deleteProperty, GetEffectiveAcl, getField, getter, makeEditable, makeReadOnly, normalizeEmail, setter, SharingPermissions } from './util'; import JSZip = require('jszip'); @@ -156,7 +156,26 @@ export function updateCachedAcls(doc: Doc) { @scriptingGlobal @Deserializable('Doc', updateCachedAcls, ['id']) export class Doc extends RefField { - @observable public static CurrentlyLoading: Doc[]; + @observable public static RecordingEvent = 0; + + // this isn't really used at the moment, but is intended to indicate whether ink stroke are passed through a gesture recognizer + static GetRecognizeGestures() { + return BoolCast(Doc.UserDoc()._recognizeGestures); + } + static SetRecognizeGestures(show: boolean) { + Doc.UserDoc()._recognizeGestures = show; + } + + // + // This controls whether fontIconButtons will display labels under their icons or not + // + static GetShowIconLabels() { + return BoolCast(Doc.UserDoc()._showLabel); + } + static SetShowIconLabels(show: boolean) { + Doc.UserDoc()._showLabel = show; + } + @observable public static CurrentlyLoading: Doc[] = []; // this assignment doesn't work. the actual assignment happens in DocumentManager's constructor // removes from currently loading display @action public static removeCurrentlyLoading(doc: Doc) { @@ -169,9 +188,6 @@ export class Doc extends RefField { // adds doc to currently loading display @action public static addCurrentlyLoading(doc: Doc) { - if (!Doc.CurrentlyLoading) { - Doc.CurrentlyLoading = []; - } if (Doc.CurrentlyLoading.indexOf(doc) === -1) { Doc.CurrentlyLoading.push(doc); } diff --git a/src/fields/RichTextUtils.ts b/src/fields/RichTextUtils.ts index 24cd078f2..5ecf25e08 100644 --- a/src/fields/RichTextUtils.ts +++ b/src/fields/RichTextUtils.ts @@ -2,20 +2,20 @@ import { AssertionError } from 'assert'; import { docs_v1 } from 'googleapis'; import { Fragment, Mark, Node } from 'prosemirror-model'; import { sinkListItem } from 'prosemirror-schema-list'; -import { Utils, DashColor } from '../Utils'; -import { Docs, DocUtils } from '../client/documents/Documents'; -import { schema } from '../client/views/nodes/formattedText/schema_rts'; +import { EditorState, TextSelection, Transaction } from 'prosemirror-state'; +import { GoogleApiClientUtils } from '../client/apis/google_docs/GoogleApiClientUtils'; import { GooglePhotos } from '../client/apis/google_docs/GooglePhotosClientUtils'; import { DocServer } from '../client/DocServer'; +import { Docs, DocUtils } from '../client/documents/Documents'; import { Networking } from '../client/Network'; import { FormattedTextBox } from '../client/views/nodes/formattedText/FormattedTextBox'; +import { schema } from '../client/views/nodes/formattedText/schema_rts'; +import { DashColor, Utils } from '../Utils'; import { Doc, Opt } from './Doc'; import { Id } from './FieldSymbols'; import { RichTextField } from './RichTextField'; import { Cast, StrCast } from './Types'; import Color = require('color'); -import { EditorState, TextSelection, Transaction } from 'prosemirror-state'; -import { GoogleApiClientUtils } from '../client/apis/google_docs/GoogleApiClientUtils'; export namespace RichTextUtils { const delimiter = '\n'; -- cgit v1.2.3-70-g09d2 From ae9ec0179e556f44bb9404f319d326321e73cb1f Mon Sep 17 00:00:00 2001 From: bobzel Date: Sun, 27 Aug 2023 22:15:27 -0400 Subject: fixed coloring of Select box in properties view for filters --- src/client/views/FilterPanel.tsx | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index b61ff35c7..0d4f4df5a 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -15,6 +15,7 @@ import { undoable } from '../util/UndoManager'; import './FilterPanel.scss'; import { FieldView } from './nodes/FieldView'; import { Handle, Tick, TooltipRail, Track } from './nodes/SliderBox-components'; +import { SettingsManager } from '../util/SettingsManager'; interface filterProps { rootDoc: Doc; @@ -278,7 +279,41 @@ export class FilterPanel extends React.Component {
- ({ + ...baseStyles, + color: SettingsManager.userColor, + background: SettingsManager.userBackgroundColor, + }), + placeholder: (baseStyles, state) => ({ + ...baseStyles, + color: SettingsManager.userColor, + background: SettingsManager.userBackgroundColor, + }), + input: (baseStyles, state) => ({ + ...baseStyles, + color: SettingsManager.userColor, + background: SettingsManager.userBackgroundColor, + }), + option: (baseStyles, state) => ({ + ...baseStyles, + color: SettingsManager.userColor, + background: !state.isFocused ? SettingsManager.userBackgroundColor : SettingsManager.userVariantColor, + }), + menuList: (baseStyles, state) => ({ + ...baseStyles, + backgroundColor: SettingsManager.userBackgroundColor, + }), + }} + placeholder="Add a filter..." + options={options} + isMulti={false} + onChange={val => this.facetClick((val as UserOptions).value)} + onKeyDown={e => e.stopPropagation()} + value={null} + closeMenuOnSelect={true} + />
{/* THE FOLLOWING CODE SHOULD BE DEVELOPER FOR BOOLEAN EXPRESSION (AND / OR) */} {/*
-- cgit v1.2.3-70-g09d2 From cfef242e9b76ba9caca2fc1871af74af6775538f Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 12 Sep 2023 20:43:20 -0400 Subject: dropping link button on same collection makes a pushpin. fixed broken undo typing to crate doc in sidebar. fixed min/max scaling for cropped images and made annotationOverlays start to use it. Fixed nested text boxes to stopPropagation on pointer down to enable editing of translations in sidebar. moved sidebar filters onto doc's filters. Added metadata filters back to sidebar. Added an -any- option to filtersPanel. fixed schema view preview window, added buttons and sliders. --- package-lock.json | 119 ++++++++++++++++----- package.json | 4 +- src/client/documents/Documents.ts | 7 +- src/client/util/CurrentUserUtils.ts | 10 +- src/client/views/FilterPanel.tsx | 20 ++-- src/client/views/PropertiesView.tsx | 7 +- src/client/views/SidebarAnnos.tsx | 30 +++--- src/client/views/StyleProvider.tsx | 2 +- .../views/collections/CollectionStackingView.tsx | 2 +- .../CollectionStackingViewFieldColumn.tsx | 6 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 44 +++++--- .../collectionSchema/CollectionSchemaView.scss | 8 +- .../collectionSchema/CollectionSchemaView.tsx | 1 + .../collections/collectionSchema/SchemaRowBox.tsx | 4 +- .../collectionSchema/SchemaTableCell.tsx | 26 ++++- src/client/views/global/globalScripts.ts | 8 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 1 - src/client/views/nodes/ImageBox.tsx | 10 +- src/client/views/nodes/PDFBox.tsx | 4 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 51 ++++++--- src/fields/Doc.ts | 1 + 21 files changed, 255 insertions(+), 110 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/package-lock.json b/package-lock.json index e0e54769a..fbfdf0136 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7244,12 +7244,97 @@ "strip-ansi": "^7.0.1" } }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, "strip-ansi": { "version": "7.1.0", "bundled": true, "requires": { "ansi-regex": "^6.0.1" } + }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + } + } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } } } }, @@ -8754,7 +8839,7 @@ } }, "string-width-cjs": { - "version": "npm:string-width@4.2.3", + "version": "npm:string-width-cjs@4.2.3", "bundled": true, "requires": { "emoji-regex": "^8.0.0", @@ -8777,7 +8862,7 @@ } }, "strip-ansi-cjs": { - "version": "npm:strip-ansi@6.0.1", + "version": "npm:strip-ansi-cjs@6.0.1", "bundled": true, "requires": { "ansi-regex": "^5.0.1" @@ -8936,7 +9021,7 @@ } }, "wrap-ansi-cjs": { - "version": "npm:wrap-ansi@7.0.0", + "version": "npm:wrap-ansi-cjs@7.0.0", "bundled": true, "requires": { "ansi-styles": "^4.0.0", @@ -14742,6 +14827,11 @@ "node-forge": "^0.10.0" } }, + "google-translate-api-browser": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/google-translate-api-browser/-/google-translate-api-browser-3.0.1.tgz", + "integrity": "sha512-KTLodkyGBWMK9IW6QIeJ2zCuju4Z0CLpbkADKo+yLhbSTD4l+CXXpQ/xaynGVAzeBezzJG6qn8MLeqOq3SmW0A==" + }, "googleapis": { "version": "40.0.1", "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-40.0.1.tgz", @@ -27327,29 +27417,6 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" }, - "translate-google-api": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/translate-google-api/-/translate-google-api-1.0.4.tgz", - "integrity": "sha512-KVXmo4+64/H1vIbnzf2zNiJ2JLeEB3jrEnNRP2EFNAGNqna/5bmw/Cps3pCHu0n3BzTOoWh9u6wFvrRYdzQ6Iw==", - "requires": { - "axios": "^0.20.0" - }, - "dependencies": { - "axios": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.20.0.tgz", - "integrity": "sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA==", - "requires": { - "follow-redirects": "^1.10.0" - } - }, - "follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" - } - } - }, "traverse-chain": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/traverse-chain/-/traverse-chain-0.1.0.tgz", diff --git a/package.json b/package.json index 67fdedeb2..d013ad74d 100644 --- a/package.json +++ b/package.json @@ -164,6 +164,7 @@ "@types/three": "^0.126.2", "@types/web": "0.0.53", "@webscopeio/react-textarea-autocomplete": "^4.9.1", + "D": "^1.0.0", "adm-zip": "^0.4.16", "archiver": "^3.1.1", "array-batcher": "^1.2.3", @@ -196,7 +197,6 @@ "cors": "^2.8.5", "csv-parser": "^3.0.0", "csv-stringify": "^6.3.0", - "D": "^1.0.0", "d3": "^7.6.1", "depcheck": "^0.9.2", "equation-editor-react": "github:bobzel/equation-editor-react#useLocally", @@ -219,6 +219,7 @@ "golden-layout": "^1.5.9", "google-auth-library": "^4.2.4", "google-maps-react": "^2.0.6", + "google-translate-api-browser": "^3.0.1", "googleapis": "^40.0.0", "googlephotos": "^0.2.5", "got": "^12.0.1", @@ -327,7 +328,6 @@ "textarea-caret": "^3.1.0", "three": "^0.127.0", "tough-cookie": "^4.0.0", - "translate-google-api": "^1.0.4", "typescript-collections": "^1.3.3", "typescript-language-server": "^0.4.0", "url-loader": "^1.1.2", diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index bb60cb329..85ee4ef59 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -145,7 +145,6 @@ class CTypeInfo extends FInfo { class DTypeInfo extends FInfo { fieldType? = 'enumeration'; values? = Array.from(Object.keys(DocumentType)); - readOnly = true; } class DateInfo extends FInfo { fieldType? = 'date'; @@ -338,11 +337,13 @@ export class DocumentOptions { // freeform properties _freeform_backgroundGrid?: BOOLt = new BoolInfo('whether background grid is shown on freeform collections'); + _freeform_scale_min?: NUMt = new NumInfo('how far out a view can zoom (used by image/videoBoxes that are clipped'); + _freeform_scale_max?: NUMt = new NumInfo('how far in a view can zoom (used by sidebar freeform views'); _freeform_scale?: NUMt = new NumInfo('how much a freeform view has been scaled (zoomed)'); _freeform_panX?: NUMt = new NumInfo('horizontal pan location of a freeform view'); _freeform_panY?: NUMt = new NumInfo('vertical pan location of a freeform view'); _freeform_noAutoPan?: BOOLt = new BoolInfo('disables autopanning when this item is dragged'); - _freeform_noZoom?: BOOLt = new BoolInfo('disables zooming'); + _freeform_noZoom?: BOOLt = new BoolInfo('disables zooming (used by Pile docs)'); //BUTTONS buttonText?: string; @@ -426,7 +427,7 @@ export class DocumentOptions { treeView_FreezeChildren?: STRt = new StrInfo('set (add, remove, add|remove) to disable adding, removing or both from collection'); sidebar_color?: string; // background color of text sidebar - sidebar_collectionType?: string; // collection type of text sidebar + sidebar_type_collection?: string; // collection type of text sidebar data_dashboards?: List; // list of dashboards used in shareddocs; text?: string; diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 8bedea562..527f251f9 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -627,6 +627,11 @@ export class CurrentUserUtils { { title: "Z order", icon: "z", toolTip: "Keep Z order on Drag", btnType: ButtonType.ToggleButton, expertMode: false, funcs: {}, scripts: { onClick: '{ return toggleRaiseOnDrag(_readOnly_);}'}}, // Only when floating document is selected in freeform ] } + static stackTools(): Button[] { + return [ + { title: "Center", icon: "align-center", toolTip: "Center Align Stack", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"center", funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform + ] + } static viewTools(): Button[] { return [ { title: "Snap", icon: "th", toolTip: "Show Snap Lines", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"snaplines", funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform @@ -682,8 +687,8 @@ export class CurrentUserUtils { static schemaTools():Button[] { return [ - {title: "Show preview", toolTip: "Show selection preview", btnType: ButtonType.ToggleButton, buttonText: "Show Preview", icon: "eye", scripts:{ onClick: '{ return toggleSchemaPreview(_readOnly_); }'} }, - {title: "Single Lines", toolTip: "Single Line Rows", btnType: ButtonType.ToggleButton, buttonText: "Single Line", icon: "eye", scripts:{ onClick: '{ return toggleSingleLineSchema(_readOnly_); }'} }, + {title: "Preview", toolTip: "Show selection preview", btnType: ButtonType.ToggleButton, icon: "portrait", scripts:{ onClick: '{ return toggleSchemaPreview(_readOnly_); }'} }, + {title: "1 Line",toolTip: "Single Line Rows", btnType: ButtonType.ToggleButton, icon: "eye", scripts:{ onClick: '{ return toggleSingleLineSchema(_readOnly_); }'} }, ]; } @@ -713,6 +718,7 @@ export class CurrentUserUtils { { title: "Ink", icon: "Ink", toolTip: "Ink functions", subMenu: CurrentUserUtils.inkTools(), expertMode: false, toolType:DocumentType.INK, funcs: { linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`}, scripts: { onClick: 'setInkToolDefaults()'} }, // Always available { title: "Doc", icon: "Doc", toolTip: "Freeform Doc tools", subMenu: CurrentUserUtils.freeTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode, true)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Always available { title: "View", icon: "View", toolTip: "View tools", subMenu: CurrentUserUtils.viewTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Always available + { title: "Stack", icon: "View", toolTip: "Stacking tools", subMenu: CurrentUserUtils.stackTools(), expertMode: false, toolType:CollectionViewType.Stacking, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Always available { title: "Web", icon: "Web", toolTip: "Web functions", subMenu: CurrentUserUtils.webTools(), expertMode: false, toolType:DocumentType.WEB, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Only when Web is selected { title: "Schema", icon: "Schema",linearBtnWidth:58,toolTip: "Schema functions",subMenu: CurrentUserUtils.schemaTools(),expertMode: false,toolType:CollectionViewType.Schema,funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Only when Schema is selected ]; diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 0d4f4df5a..a601706ce 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -235,7 +235,7 @@ export class FilterPanel extends React.Component { facetValues = (facetHeader: string) => { const allCollectionDocs = new Set(); SearchUtil.foreachRecursiveDoc(this.targetDocChildren, (depth: number, doc: Doc) => allCollectionDocs.add(doc)); - const set = new Set([String.fromCharCode(127) + '--undefined--']); + const set = new Set([String.fromCharCode(127) + '--undefined--', Doc.FilterAny]); if (facetHeader === 'tags') allCollectionDocs.forEach(child => StrListCast(child[facetHeader]) @@ -257,24 +257,16 @@ export class FilterPanel extends React.Component { }; render() { - // console.log('this is frist one today ' + this._allFacets); - this._allFacets.forEach(element => console.log(element)); - // const options = Object.entries(this._documentOptions).forEach((pair: [string, FInfo]) => pair[1].filterable ).map(facet => value: facet, label: facet) //this._allFacets.filter(facet => this.activeFacetHeaders.indexOf(facet) === -1).map(facet => ({ value: facet, label: facet })); - // console.log('HEELLLLLL ' + DocumentOptions); - - let filteredOptions: string[] = ['author', 'tags', 'text', 'acl-Guest']; + let filteredOptions: string[] = ['author', 'tags', 'text', 'acl-Guest', ...this._allFacets.filter(facet => facet[0] === facet.charAt(0).toUpperCase())]; Object.entries(this._documentOptions).forEach((pair: [string, FInfo]) => { if (pair[1].filterable) { filteredOptions.push(pair[0]); - console.log('THIS IS FILTERABLE ALKDJFIIEII' + filteredOptions); } }); let options = filteredOptions.map(facet => ({ value: facet, label: facet })); - // Object.entries(this._documentOptions).forEach((pair: [string, FInfo]) => console.log('this is first piar ' + pair[0] + ' this is second piar ' + pair[1].filterable)); - return (
@@ -398,13 +390,13 @@ export class FilterPanel extends React.Component {
filter.split(Doc.FilterSep)[0] === facetHeader && filter.split(Doc.FilterSep)[1] == facetValue) - ?.split(Doc.FilterSep)[2] === 'check' - } + ?.split(Doc.FilterSep)[2] ?? '' + )} type={type} - onChange={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, e.target.checked ? 'check' : 'remove'), 'set filter')} + onChange={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, e.target.checked ? (fval === Doc.FilterAny ? 'exists' : 'check') : 'remove'), 'set filter')} /> {facetValue}
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 699aafe80..21b6bfac5 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -18,7 +18,7 @@ import { ComputedField } from '../../fields/ScriptField'; import { Cast, DocCast, NumCast, StrCast } from '../../fields/Types'; import { GetEffectiveAcl, normalizeEmail, SharingPermissions } from '../../fields/util'; import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, Utils } from '../../Utils'; -import { DocumentType } from '../documents/DocumentTypes'; +import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; import { DocumentManager } from '../util/DocumentManager'; import { GroupManager } from '../util/GroupManager'; import { LinkManager } from '../util/LinkManager'; @@ -122,6 +122,9 @@ export class PropertiesView extends React.Component { @computed get isInk() { return this.selectedDoc?.type === DocumentType.INK; } + @computed get isStack() { + return this.selectedDoc?.type_collection === CollectionViewType.Stacking; + } rtfWidth = () => (!this.selectedDoc ? 0 : Math.min(this.selectedDoc?.[Width](), this.props.width - 20)); rtfHeight = () => (!this.selectedDoc ? 0 : this.rtfWidth() <= this.selectedDoc?.[Width]() ? Math.min(this.selectedDoc?.[Height](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT); @@ -1096,6 +1099,8 @@ export class PropertiesView extends React.Component { @computed get transformEditor() { return (
+ {!this.isStack ? null : this.getNumber('Gap', ' px', 0, 200, NumCast(this.selectedDoc!.gridGap), (val: number) => !isNaN(val) && (this.selectedDoc!.gridGap = val))} + {!this.isStack ? null : this.getNumber('xMargin', ' px', 0, 500, NumCast(this.selectedDoc!.xMargin), (val: number) => !isNaN(val) && (this.selectedDoc!.xMargin = val))} {this.isInk ? this.controlPointsButton : null} {this.getNumber('Width', ' px', 0, Math.max(1000, this.shapeWid), this.shapeWid, (val: number) => !isNaN(val) && (this.shapeWid = val), 1000, 1)} {this.getNumber('Height', ' px', 0, Math.max(1000, this.shapeHgt), this.shapeHgt, (val: number) => !isNaN(val) && (this.shapeHgt = val), 1000, 1)} diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx index ff347d65f..1e1b8e0e6 100644 --- a/src/client/views/SidebarAnnos.tsx +++ b/src/client/views/SidebarAnnos.tsx @@ -62,12 +62,9 @@ export class SidebarAnnos extends React.Component { DocListCast(this.props.rootDoc[this.sidebarKey]).forEach(doc => keys.add(StrCast(doc.author))); return Array.from(keys.keys()).sort(); } - get filtersKey() { - return '_' + this.sidebarKey + '_childFilters'; - } anchorMenuClick = (anchor: Doc, filterExlusions?: string[]) => { - const startup = StrListCast(this.props.rootDoc.childFilters) + const startup = this.childFilters() .map(filter => filter.split(':')[0]) .join(' '); const target = Docs.Create.TextDocument(startup, { @@ -151,8 +148,9 @@ export class SidebarAnnos extends React.Component { }; makeDocUnfiltered = (doc: Doc) => { if (DocListCast(this.props.rootDoc[this.sidebarKey]).find(anno => Doc.AreProtosEqual(doc.layout_unrendered ? DocCast(doc.annotationOn) : doc, anno))) { - if (this.props.layoutDoc[this.filtersKey]) { - this.props.layoutDoc[this.filtersKey] = new List(); + if (this.childFilters()) { + // if any child filters exist, get rid of them + this.props.layoutDoc._childFilters = new List(); } return true; } @@ -178,7 +176,7 @@ export class SidebarAnnos extends React.Component { addDocument = (doc: Doc | Doc[]) => this.props.sidebarAddDocument(doc, this.sidebarKey); moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean) => this.props.moveDocument(doc, targetCollection, addDocument, this.sidebarKey); removeDocument = (doc: Doc | Doc[]) => this.props.removeDocument(doc, this.sidebarKey); - childFilters = () => [...StrListCast(this.props.layoutDoc._childFilters), ...StrListCast(this.props.layoutDoc[this.filtersKey])]; + childFilters = () => StrListCast(this.props.layoutDoc._childFilters); layout_showTitle = () => 'title'; setHeightCallback = (height: number) => this.props.setHeight?.(height + this.filtersHeight()); sortByLinkAnchorY = (a: Doc, b: Doc) => { @@ -188,25 +186,25 @@ export class SidebarAnnos extends React.Component { }; render() { const renderTag = (tag: string) => { - const active = StrListCast(this.props.rootDoc[this.filtersKey]).includes(`tags::${tag}::check`); + const active = this.childFilters().includes(`tags${Doc.FilterSep}${tag}${Doc.FilterSep}check`); return ( -
Doc.setDocFilter(this.props.rootDoc, 'tags', tag, 'check', true, this.sidebarKey, e.shiftKey)}> +
Doc.setDocFilter(this.props.rootDoc, 'tags', tag, 'check', true, undefined, e.shiftKey)}> {tag}
); }; const renderMeta = (tag: string, dflt: FieldResult) => { - const active = StrListCast(this.props.rootDoc[this.filtersKey]).includes(`${tag}:${dflt}:exists`); + const active = this.childFilters().includes(`${tag}${Doc.FilterSep}${Doc.FilterAny}${Doc.FilterSep}exists`); return ( -
Doc.setDocFilter(this.props.rootDoc, tag, dflt, 'exists', true, this.sidebarKey, e.shiftKey)}> +
Doc.setDocFilter(this.props.rootDoc, tag, Doc.FilterAny, 'exists', true, undefined, e.shiftKey)}> {tag}
); }; const renderUsers = (user: string) => { - const active = StrListCast(this.props.rootDoc[this.filtersKey]).includes(`author:${user}:check`); + const active = this.childFilters().includes(`author:${user}:check`); return ( -
Doc.setDocFilter(this.props.rootDoc, 'author', user, 'check', true, this.sidebarKey, e.shiftKey)}> +
Doc.setDocFilter(this.props.rootDoc, 'author', user, 'check', true, undefined, e.shiftKey)}> {user}
); @@ -224,11 +222,11 @@ export class SidebarAnnos extends React.Component { height: '100%', }}>
e.stopPropagation()}> - {this.allUsers.map(renderUsers)} + {this.allUsers.length > 1 ? this.allUsers.map(renderUsers) : null} {this.allHashtags.map(renderTag)} - {/* {Array.from(this.allMetadata.keys()) + {Array.from(this.allMetadata.keys()) .sort() - .map(key => renderMeta(key, this.allMetadata.get(key)))} */} + .map(key => renderMeta(key, this.allMetadata.get(key)))}
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 85aa5ad83..0a14b93f7 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -317,7 +317,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt ({ + items={[ DocumentManager.Instance.getDocumentView(Doc.ActiveDashboard)!, ...(props?.docViewPath?.()??[]), ...(props?.DocumentView?[props?.DocumentView?.()]:[])].map(dv => ({ text: StrCast(dv.rootDoc.title), val: dv as any, style: {color:SettingsManager.userColor, background:SettingsManager.userBackgroundColor}, diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 9ba4cb6cf..8c40567d3 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -138,7 +138,7 @@ export class CollectionStackingView extends CollectionSubView diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 3aadeffcd..3598d548a 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -361,7 +361,11 @@ export class CollectionStackingViewFieldColumn extends React.Component +
e.stopPropagation()} + className="collectionStackingView-addDocumentButton" + style={{ width: 'calc(100% - 25px)', maxWidth: this.props.columnWidth / this.props.numGroupColumns - 25, marginBottom: 10 }}> number; @@ -421,11 +422,27 @@ export class CollectionFreeFormView extends CollectionSubView { - if (this.Document._isGroup || this.Document._freeform_noZoom) return; + if (this.Document._isGroup || this.Document[this.scaleFieldKey + '_noZoom']) return; let deltaScale = deltaY > 0 ? 1 / 1.05 : 1.05; if (deltaScale < 0) deltaScale = -deltaScale; const [x, y] = this.getTransform().transformPoint(pointX, pointY); @@ -1032,12 +1049,15 @@ export class CollectionFreeFormView extends CollectionSubView 20) { deltaScale = 20 / invTransform.Scale; } - if (deltaScale < 1 && invTransform.Scale <= NumCast(this.rootDoc._freeform_scale_min, 1) && this.isAnnotationOverlay) { + if (deltaScale < 1 && invTransform.Scale <= NumCast(this.rootDoc[this.scaleFieldKey + '_min'])) { this.setPan(0, 0); return; } - if (deltaScale * invTransform.Scale < NumCast(this.rootDoc._freeform_scale_min, 1) && this.isAnnotationOverlay) { - deltaScale = NumCast(this.rootDoc._freeform_scale_min, 1) / invTransform.Scale; + if (deltaScale * invTransform.Scale > NumCast(this.rootDoc[this.scaleFieldKey + '_max'], Number.MAX_VALUE)) { + deltaScale = NumCast(this.rootDoc[this.scaleFieldKey + '_max'], 1) / invTransform.Scale; + } + if (deltaScale * invTransform.Scale < NumCast(this.rootDoc[this.scaleFieldKey + '_min'], this.isAnnotationOverlay ? 1 : 0)) { + deltaScale = NumCast(this.rootDoc[this.scaleFieldKey + '_min'], 1) / invTransform.Scale; } const localTransform = invTransform.scaleAbout(deltaScale, x, y); @@ -1527,12 +1547,6 @@ export class CollectionFreeFormView extends CollectionSubView .schema-column-header:nth-child(2) > .left { @@ -205,7 +211,7 @@ overflow-x: hidden; overflow-y: auto; padding: 5px; - display: inline-block; + display: inline-flex; } .schema-row { diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 5c7dcc1a4..d757d5349 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -836,6 +836,7 @@ export class CollectionSchemaView extends CollectionSubView() {
this.props.isContentActive() && e.stopPropagation()} ref={r => { // prevent wheel events from passively propagating up through containers diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 5b4fc34bb..4e418728f 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -16,7 +16,7 @@ import { CollectionSchemaView } from './CollectionSchemaView'; import './CollectionSchemaView.scss'; import { SchemaTableCell } from './SchemaTableCell'; import { Transform } from '../../../util/Transform'; -import { IconButton } from 'browndash-components'; +import { IconButton, Size } from 'browndash-components'; import { CgClose } from 'react-icons/cg'; import { FaExternalLinkAlt } from 'react-icons/fa'; import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../../Utils'; @@ -117,6 +117,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { } + size={Size.XSMALL} onPointerDown={e => setupMoveUpEvents( this, @@ -133,6 +134,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { } + size={Size.XSMALL} onPointerDown={e => setupMoveUpEvents( this, diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 1c9c0de53..e18f27fb0 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -325,10 +325,34 @@ export class SchemaEnumerationCell extends React.Component const { color, textDecoration, fieldProps, cursor, pointerEvents } = SchemaTableCell.renderProps(this.props); const options = this.props.options?.map(facet => ({ value: facet, label: facet })); return ( -
+
filter.split(Doc.FilterSep)[0] === facetHeader) - ?.split(Doc.FilterSep)[1] ?? '-empty-' + ?.split(Doc.FilterSep)[1] } + style={{ color: SettingsManager.userColor, background: SettingsManager.userBackgroundColor }} onBlur={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, e.currentTarget.value, !e.currentTarget.value ? 'remove' : 'match'), 'set text filter')} onKeyDown={e => e.key === 'Enter' && undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, e.currentTarget.value, !e.currentTarget.value ? 'remove' : 'match'), 'set text filter')(e)} /> diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 775ccd067..96b2ddf70 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -318,7 +318,9 @@ export function DefaultStyleProvider(doc: Opt, props: Opt ({ + items={[ ...(dashView ? [dashView]: []), ...(props?.docViewPath?.()??[]), ...(props?.DocumentView?[props?.DocumentView?.()]:[])] + .filter(dv => StrListCast(dv.rootDoc.childFilters).length || StrListCast(dv.rootDoc.childRangeFilters).length) + .map(dv => ({ text: StrCast(dv.rootDoc.title), val: dv as any, style: {color:SettingsManager.userColor, background:SettingsManager.userBackgroundColor}, diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 0ee83bc08..198cbe851 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -204,7 +204,7 @@ export class LinkDocPreview extends React.Component { }; @computed get previewHeader() { return !this._linkDoc || !this._markerTargetDoc || !this._targetDoc || !this._linkSrc ? null : ( -
+
Edit Link
} placement="top">
@@ -302,7 +302,7 @@ export class LinkDocPreview extends React.Component { className="linkDocPreview" ref={this._linkDocRef} onPointerDown={this.followLinkPointerDown} - style={{ left: this.props.location[0], top: this.props.location[1], width: this.width() + borders, height: this.height() + borders + (this.props.showHeader ? 37 : 0) }}> + style={{ borderColor: SettingsManager.userColor, left: this.props.location[0], top: this.props.location[1], width: this.width() + borders, height: this.height() + borders + (this.props.showHeader ? 37 : 0) }}> {this.docPreview}
); -- cgit v1.2.3-70-g09d2 From 2b96f355ea7f4aa0e1fcf0dbee8ce6bf6e8f09d4 Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 18 Sep 2023 14:27:05 -0400 Subject: revised how to do filtering by links. --- src/client/documents/Documents.ts | 28 +++++++--------------------- src/client/views/FilterPanel.tsx | 15 +++++++-------- src/client/views/InkTangentHandles.tsx | 1 - src/client/views/nodes/MapBox/MapBox.tsx | 6 +++--- src/fields/Doc.ts | 25 ++++++++++++++++++++----- 5 files changed, 37 insertions(+), 38 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 055950e6f..254be67b9 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -15,7 +15,7 @@ import { BoolCast, Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast } fro import { AudioField, CsvField, ImageField, PdfField, VideoField, WebField, YoutubeField } from '../../fields/URLField'; import { inheritParentAcls, SharingPermissions } from '../../fields/util'; import { Upload } from '../../server/SharedMediaTypes'; -import { aggregateBounds, OmitKeys, Utils } from '../../Utils'; +import { OmitKeys, Utils } from '../../Utils'; import { YoutubeBox } from '../apis/youtube/YoutubeBox'; import { DocServer } from '../DocServer'; import { Networking } from '../Network'; @@ -1296,20 +1296,6 @@ export namespace DocUtils { for (const facetKey of Object.keys(filterFacets).filter(fkey => fkey !== 'cookies' && fkey !== Utils.noDragsDocFilter.split(Doc.FilterSep)[0])) { const facet = filterFacets[facetKey]; - let links = true; - const linkedTo = filterFacets['-linkedTo'] && Array.from(Object.keys(filterFacets['-linkedTo']))?.[0]; - const linkedToField = filterFacets['-linkedTo']?.[linkedTo]; - const allLinks = linkedTo && linkedToField ? LinkManager.Instance.getAllRelatedLinks(d) : []; - // prettier-ignore - if (linkedTo) { - if (allLinks.some(d => linkedTo === Field.toScriptString(DocCast(DocCast(d.link_anchor_1)?.[linkedToField]))) || // - allLinks.some(d => linkedTo === Field.toScriptString(DocCast(DocCast(d.link_anchor_2)?.[linkedToField])))) - { - links = true; - } - else links = false - } - // facets that match some value in the field of the document (e.g. some text field) const matches = Object.keys(facet).filter(value => value !== 'cookies' && facet[value] === 'match'); @@ -1319,16 +1305,16 @@ export namespace DocUtils { // metadata facets that exist const exists = Object.keys(facet).filter(value => facet[value] === 'exists'); - // metadata facets that exist + // facets that unset metadata (a hack for making cookies work) const unsets = Object.keys(facet).filter(value => facet[value] === 'unset'); - // facets that have an x next to them + // facets that specify that a field must not match a specific value const xs = Object.keys(facet).filter(value => facet[value] === 'x'); - if (!linkedTo && !unsets.length && !exists.length && !xs.length && !checks.length && !matches.length) return true; + if (!unsets.length && !exists.length && !xs.length && !checks.length && !matches.length) return true; const failsNotEqualFacets = !xs.length ? false : xs.some(value => Doc.matchFieldValue(d, facetKey, value)); const satisfiesCheckFacets = !checks.length ? true : checks.some(value => Doc.matchFieldValue(d, facetKey, value)); - const satisfiesExistsFacets = !exists.length ? true : exists.some(value => d[facetKey] !== undefined); + const satisfiesExistsFacets = !exists.length ? true : exists.some(value => (facetKey !== '-linkedTo' ? d[facetKey] !== undefined : LinkManager.Instance.getAllRelatedLinks(d).length)); const satisfiesUnsetsFacets = !unsets.length ? true : unsets.some(value => d[facetKey] === undefined); const satisfiesMatchFacets = !matches.length ? true @@ -1344,11 +1330,11 @@ export namespace DocUtils { }); // if we're ORing them together, the default return is false, and we return true for a doc if it satisfies any one set of criteria if (parentCollection?.childFilters_boolean === 'OR') { - if (links && satisfiesUnsetsFacets && satisfiesExistsFacets && satisfiesCheckFacets && !failsNotEqualFacets && satisfiesMatchFacets) return true; + if (satisfiesUnsetsFacets && satisfiesExistsFacets && satisfiesCheckFacets && !failsNotEqualFacets && satisfiesMatchFacets) return true; } // if we're ANDing them together, the default return is true, and we return false for a doc if it doesn't satisfy any set of criteria else { - if (!links || !satisfiesUnsetsFacets || !satisfiesExistsFacets || !satisfiesCheckFacets || failsNotEqualFacets || (matches.length && !satisfiesMatchFacets)) return false; + if (!satisfiesUnsetsFacets || !satisfiesExistsFacets || !satisfiesCheckFacets || failsNotEqualFacets || (matches.length && !satisfiesMatchFacets)) return false; } } return parentCollection?.childFilters_boolean === 'OR' ? false : true; diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 4af29c70e..312dc3a70 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -56,7 +56,7 @@ export class FilterPanel extends React.Component { @computed get _allFacets() { // trace(); - const noviceReqFields = ['author', 'tags', 'text', 'type']; + const noviceReqFields = ['author', 'tags', 'text', 'type', '-linkedTo']; const noviceLayoutFields: string[] = []; //["_layout_curPage"]; const noviceFields = [...noviceReqFields, ...noviceLayoutFields]; @@ -118,7 +118,7 @@ export class FilterPanel extends React.Component { // } gatherFieldValues(childDocs: Doc[], facetKey: string) { - const valueSet = new Set(); + const valueSet = new Set(StrListCast(this.props.rootDoc.childFilters).map(filter => filter.split(Doc.FilterSep)[1])); let rtFields = 0; let subDocs = childDocs; if (subDocs.length > 0) { @@ -127,7 +127,6 @@ export class FilterPanel extends React.Component { newarray = []; subDocs.forEach(t => { const facetVal = t[facetKey]; - // console.log("facetVal " + facetVal) if (facetVal instanceof RichTextField || typeof facetVal === 'string') rtFields++; facetVal !== undefined && valueSet.add(Field.toString(facetVal as Field)); (facetVal === true || facetVal == false) && valueSet.add(Field.toString(!facetVal)); @@ -182,14 +181,14 @@ export class FilterPanel extends React.Component { }); if (facetHeader === 'text') { - return { facetHeader: facetHeader, renderType: 'text' }; + return { facetHeader, renderType: 'text' }; } else if (facetHeader !== 'tags' && nonNumbers / facetValues.strings.length < 0.1) { const extendedMinVal = minVal - Math.min(1, Math.floor(Math.abs(maxVal - minVal) * 0.1)); const extendedMaxVal = Math.max(minVal + 1, maxVal + Math.min(1, Math.ceil(Math.abs(maxVal - minVal) * 0.05))); const ranged = Doc.readDocRangeFilter(this.targetDoc, facetHeader); // not the filter range, but the zooomed in range on the filter - return { facetHeader: facetHeader, renderType: 'range', domain: [extendedMinVal, extendedMaxVal], range: ranged ? ranged : [extendedMinVal, extendedMaxVal] }; + return { facetHeader, renderType: 'range', domain: [extendedMinVal, extendedMaxVal], range: ranged ? ranged : [extendedMinVal, extendedMaxVal] }; } else { - return { facetHeader: facetHeader, renderType: 'checkbox' }; + return { facetHeader, renderType: 'checkbox' }; } }) ); @@ -236,7 +235,7 @@ export class FilterPanel extends React.Component { facetValues = (facetHeader: string) => { const allCollectionDocs = new Set(); SearchUtil.foreachRecursiveDoc(this.targetDocChildren, (depth: number, doc: Doc) => allCollectionDocs.add(doc)); - const set = new Set([String.fromCharCode(127) + '--undefined--', Doc.FilterAny]); + const set = new Set([...StrListCast(this.props.rootDoc.childFilters).map(filter => filter.split(Doc.FilterSep)[1]), Doc.FilterNone, Doc.FilterAny]); if (facetHeader === 'tags') allCollectionDocs.forEach(child => StrListCast(child[facetHeader]) @@ -404,7 +403,7 @@ export class FilterPanel extends React.Component { ?.split(Doc.FilterSep)[2] ?? '' )} type={type} - onChange={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, e.target.checked ? (fval === Doc.FilterAny ? 'exists' : 'check') : 'remove'), 'set filter')} + onChange={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, e.target.checked ? 'check' : 'remove'), 'set filter')} /> {facetValue}
diff --git a/src/client/views/InkTangentHandles.tsx b/src/client/views/InkTangentHandles.tsx index 71e0ff63c..65f6a6dfa 100644 --- a/src/client/views/InkTangentHandles.tsx +++ b/src/client/views/InkTangentHandles.tsx @@ -12,7 +12,6 @@ import { UndoManager } from '../util/UndoManager'; import { Colors } from './global/globalEnums'; import { InkingStroke } from './InkingStroke'; import { InkStrokeProperties } from './InkStrokeProperties'; -import { DocumentView } from './nodes/DocumentView'; export interface InkHandlesProps { inkDoc: Doc; inkView: InkingStroke; diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index 3e22c0d0e..d7469e530 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -350,7 +350,7 @@ export class MapBox extends ViewBoxAnnotatableComponent color !== '' && DashColor(color).alpha() !== 1; return isTransparent(StrCast(doc[key])); } + if (key === '-linkedTo') { + // links are not a field value, so handled here. value is an expression of form ([field=]idToDoc("...")) + const allLinks = LinkManager.Instance.getAllRelatedLinks(doc); + const matchLink = (value: string, anchor: Doc) => { + const linkedToExp = value?.split('='); + if (linkedToExp.length === 1) return Field.toScriptString(anchor) === value; + return Field.toScriptString(DocCast(anchor[linkedToExp[0]])) === linkedToExp[1]; + }; + // prettier-ignore + return (value === Doc.FilterNone && !allLinks.length) || + (value === Doc.FilterAny && !!allLinks.length) || + (allLinks.some(link => matchLink(value,DocCast(link.link_anchor_1)) || + matchLink(value,DocCast(link.link_anchor_2)) )); + } if (typeof value === 'string') { value = value.replace(`,${Utils.noRecursionHack}`, ''); } const fieldVal = doc[key]; if (Cast(fieldVal, listSpec('string'), []).length) { - const vals = Cast(fieldVal, listSpec('string'), []); + const vals = StrListCast(fieldVal); const docs = vals.some(v => (v as any) instanceof Doc); if (docs) return value === Field.toString(fieldVal as Field); return vals.some(v => v.includes(value)); // bcz: arghh: Todo: comparison should be parameterized as exact, or substring } const fieldStr = Field.toString(fieldVal as Field); - return fieldStr.includes(value) || (value === String.fromCharCode(127) + '--undefined--' && fieldVal === undefined); // bcz: arghh: Todo: comparison should be parameterized as exact, or substring + return fieldStr.includes(value) || (value === Doc.FilterAny && fieldVal !== undefined) || (value === Doc.FilterNone && fieldVal === undefined); // bcz: arghh: Todo: comparison should be parameterized as exact, or substring } export function deiconifyView(doc: Doc) { @@ -1520,18 +1534,19 @@ export namespace Doc { export const FilterSep = '::'; export const FilterAny = '--any--'; + export const FilterNone = '--undefined--'; // filters document in a container collection: // all documents with the specified value for the specified key are included/excluded // based on the modifiers :"check", "x", undefined - export function setDocFilter(container: Opt, key: string, value: any, modifiers: 'removeAll' | 'remove' | 'match' | 'check' | 'x' | 'exists' | 'unset', toggle?: boolean, fieldPrefix?: string, append: boolean = true) { + export function setDocFilter(container: Opt, key: string, value: any, modifiers: 'remove' | 'match' | 'check' | 'x' | 'exists' | 'unset', toggle?: boolean, fieldPrefix?: string, append: boolean = true) { if (!container) return; const filterField = '_' + (fieldPrefix ? fieldPrefix + '_' : '') + 'childFilters'; const childFilters = StrListCast(container[filterField]); runInAction(() => { for (let i = 0; i < childFilters.length; i++) { const fields = childFilters[i].split(FilterSep); // split key:value:modifier - if (fields[0] === key && (fields[1] === value.toString() || modifiers === 'match' || modifiers === 'removeAll' || (fields[2] === 'match' && modifiers === 'remove'))) { + if (fields[0] === key && (fields[1] === value.toString() || modifiers === 'match' || (fields[2] === 'match' && modifiers === 'remove'))) { if (fields[2] === modifiers && modifiers && fields[1] === value.toString()) { if (toggle) modifiers = 'remove'; else return; @@ -1543,7 +1558,7 @@ export namespace Doc { } if (!childFilters.length && modifiers === 'match' && value === undefined) { container[filterField] = undefined; - } else if (modifiers !== 'remove' && modifiers !== 'removeAll') { + } else if (modifiers !== 'remove') { !append && (childFilters.length = 0); childFilters.push(key + FilterSep + value + FilterSep + modifiers); container[filterField] = new List(childFilters); -- cgit v1.2.3-70-g09d2 From 84aa8806a62e2e957e8281d7d492139e3d8225f2 Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 18 Sep 2023 14:41:53 -0400 Subject: removed filter checkboxes for list values since they don't work. fixed any/undefined filtering for tags or other list fields. --- src/client/views/FilterPanel.tsx | 8 ++++++-- src/fields/Doc.ts | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 312dc3a70..69ceb0f65 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -17,6 +17,7 @@ import { FieldView } from './nodes/FieldView'; import { Handle, Tick, TooltipRail, Track } from './nodes/SliderBox-components'; import { SettingsManager } from '../util/SettingsManager'; import { Id } from '../../fields/FieldSymbols'; +import { List } from '../../fields/List'; interface filterProps { rootDoc: Doc; @@ -245,8 +246,11 @@ export class FilterPanel extends React.Component { else allCollectionDocs.forEach(child => { const fieldVal = child[facetHeader] as Field; - set.add(Field.toString(fieldVal)); - (fieldVal === true || fieldVal === false) && set.add((!fieldVal).toString()); + if (!(fieldVal instanceof List)) { + // currently we have no good way of filtering based on a field that is a list + set.add(Field.toString(fieldVal)); + (fieldVal === true || fieldVal === false) && set.add((!fieldVal).toString()); + } }); const facetValues = Array.from(set).filter(v => v); diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 78a03d782..56b97e42f 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1481,14 +1481,18 @@ export namespace Doc { value = value.replace(`,${Utils.noRecursionHack}`, ''); } const fieldVal = doc[key]; + // prettier-ignore + if ((value === Doc.FilterAny && fieldVal !== undefined) || + (value === Doc.FilterNone && fieldVal === undefined)) { + return true; + } if (Cast(fieldVal, listSpec('string'), []).length) { const vals = StrListCast(fieldVal); const docs = vals.some(v => (v as any) instanceof Doc); if (docs) return value === Field.toString(fieldVal as Field); return vals.some(v => v.includes(value)); // bcz: arghh: Todo: comparison should be parameterized as exact, or substring } - const fieldStr = Field.toString(fieldVal as Field); - return fieldStr.includes(value) || (value === Doc.FilterAny && fieldVal !== undefined) || (value === Doc.FilterNone && fieldVal === undefined); // bcz: arghh: Todo: comparison should be parameterized as exact, or substring + return Field.toString(fieldVal as Field).includes(value); // bcz: arghh: Todo: comparison should be parameterized as exact, or substring } export function deiconifyView(doc: Doc) { -- cgit v1.2.3-70-g09d2