diff options
| -rw-r--r-- | package-lock.json | 91 | ||||
| -rw-r--r-- | src/client/documents/Documents.ts | 7 | ||||
| -rw-r--r-- | src/client/views/FilterPanel.scss | 34 | ||||
| -rw-r--r-- | src/client/views/FilterPanel.tsx | 160 | ||||
| -rw-r--r-- | src/client/views/PropertiesView.scss | 11 | ||||
| -rw-r--r-- | src/client/views/PropertiesView.tsx | 5 | ||||
| -rw-r--r-- | src/fields/Doc.ts | 5 |
7 files changed, 287 insertions, 26 deletions
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/documents/Documents.ts b/src/client/documents/Documents.ts index 8eeceaa15..5d7ca6f6d 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<any>[] = []; +} type BOOLt = BoolInfo | boolean; type NUMt = NumInfo | number; type STRt = StrInfo | string; +type LISTt = ListInfo | List<any>; 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.scss b/src/client/views/FilterPanel.scss index 4f0460659..78e7904b8 100644 --- a/src/client/views/FilterPanel.scss +++ b/src/client/views/FilterPanel.scss @@ -135,7 +135,7 @@ .filterBox-addFilter { width: 120px; - background-color: #e9e9e9; + backgroundcolor: #e9e9e9; border-radius: 12px; padding: 5px; margin: 5px; @@ -188,6 +188,8 @@ margin-bottom: 10px; margin-left: 5px; overflow: auto; + + } } @@ -199,14 +201,36 @@ // float:right; .filterBox-facetHeader-collapse{ - float: right; - justify-items: right; - align-items: flex-end; + // float: right; + // justify-items: right; + // align-items: flex-end; margin-left: auto; - margin-right: 9px; + // margin-right: 9px; + + float: right; + font-size: 16; + } + + .filterBox-facetHeader-remove{ + // margin-left: auto; + float: right; + font-size: 16; + font-weight:bold; } + + } +.filterbox-collpasedAndActive{ + // 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 68d29942b..d6638df46 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -11,12 +11,15 @@ 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 + interface filterProps { rootDoc: Doc; } + @observer export class FilterPanel extends React.Component<filterProps> { public static LayoutString(fieldKey: string) { @@ -86,6 +89,7 @@ export class FilterPanel extends React.Component<filterProps> { 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)); @@ -99,21 +103,42 @@ export class FilterPanel extends React.Component<filterProps> { } // } // }); + return { strings: Array.from(valueSet.keys()), rtFields }; } + + public removeFilter = (filterName: string) => { Doc.setDocFilter(this.targetDoc, filterName, undefined, 'remove'); Doc.setDocRangeFilter(this.targetDoc, filterName, undefined); }; @observable _chosenFacets = new ObservableMap<string, 'text' | 'checkbox' | 'slider' | 'range'>(); + @observable _chosenFacetsCollapse = new ObservableMap<string, boolean>(); + @observable _collapseReturnKeys = new Array(); + + + // this computed function gets the active filters and maps them to their headers + + @computed get currentActiveFilterz(){ + const filters = new Map<string, string>(); + //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) const facets = new Map<string, 'text' | 'checkbox' | 'slider' | 'range'>(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 */ @@ -138,11 +163,75 @@ export class FilterPanel extends React.Component<filterProps> { 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); + 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, + // 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) => { + + this._collapseReturnKeys.splice(0) + + for (var key of this.facetValues(facetHeader)){ + // console.log("key : " + key ) + if (this.currentActiveFilterz.get(key)){ + // console.log("WEREEE HERHEHHHHEHHHHEEE") + this._collapseReturnKeys.push(key) + }} + + return (<div className = " filterbox-collpasedAndActive"> + + {this._collapseReturnKeys.join(', ') } + {/* .toString()} */} + </div>) + + + } + + + + facetValues = (facetHeader: string) => { const allCollectionDocs = new Set<Doc>(); SearchBox.foreachRecursiveDoc(this.targetDocChildren, (depth: number, doc: Doc) => allCollectionDocs.add(doc)); @@ -167,10 +256,10 @@ export class FilterPanel extends React.Component<filterProps> { return nonNumbers / facetValues.length > 0.1 ? facetValues.sort() : facetValues.sort((n1: string, n2: string) => Number(n1) - Number(n2)); }; + 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 ( <div className="filterBox-treeView"> <div className="filterBox-select"> @@ -196,15 +285,49 @@ export class FilterPanel extends React.Component<filterProps> { <div className = "filterBox-facetHeader-Header"> </div> {facetHeader.charAt(0).toUpperCase() + facetHeader.slice(1)} - <div className = "filterBox-facetHeader-collapse"> - <AiOutlineMinusSquare/> - {/* <CiCircleRemove/> */} - </div> - + <div className = "filterBox-facetHeader-collapse" + onClick = {action((e) => { + + 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) ? <AiOutlinePlusSquare/> : <AiOutlineMinusSquare/> } + + </div> + + <div className='filterBox-facetHeader-remove' + onClick = {action((e) => { + for (var key of this.facetValues(facetHeader)){ + if (this.currentActiveFilterz.get(key)){ + Doc.setDocFilter(this.targetDoc, facetHeader, key, 'remove') + }} + + this.activeFacets.delete(facetHeader) + this._chosenFacets.delete(facetHeader) + this._chosenFacetsCollapse.delete(facetHeader) + + })} > + + <CiCircleRemove/> </div> + {/* </div> */} + </div> - - {this.displayFacetValueFilterUIs(this.activeFacets.get(facetHeader), facetHeader)} + { this._chosenFacetsCollapse.get(facetHeader) ? + // <div className = 'filterbox-collpasedAndActive' style={{backgroundColor: 'yellow', fontSize: 50}} > {this.sortingCurrentFacetValues(facetHeader)} </div> && this._collapseReturnKeys.splice(0) + this.sortingCurrentFacetValues(facetHeader) + // && this._collapseReturnKeys.splice(0) + : this.displayFacetValueFilterUIs(this.activeFacets.get(facetHeader), facetHeader) } + {/* */} </div> ))} </div> @@ -227,19 +350,24 @@ export class FilterPanel extends React.Component<filterProps> { /> ); case 'checkbox': + return this.facetValues(facetHeader).map(fval => { + const facetValue = fval; return ( <div> <input style={{ width: 20, marginLeft: 20 }} - checked={ - StrListCast(this.targetDoc._childFilters) - .find(filter => 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} </div> @@ -248,3 +376,5 @@ export class FilterPanel extends React.Component<filterProps> { } } } + + diff --git a/src/client/views/PropertiesView.scss b/src/client/views/PropertiesView.scss index b79486167..f7dc1dc68 100644 --- a/src/client/views/PropertiesView.scss +++ b/src/client/views/PropertiesView.scss @@ -26,6 +26,17 @@ padding: 5px 10px; } + .propertiesView-propAndInfoGrouping{ + display: flex; + } + + .propertiesView-info{ + margin-top: 20; + margin-right: 10; + float: right; + font-size: 20; + } + .propertiesView-sharing { //border-bottom: 1px solid black; diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 27b9c3c7a..35ca5dea4 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -587,7 +587,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { return ( <div> - <div className = "propertiesView-wordType">Type</div> + Type + {/* <div className = "propertiesView-wordType">Type</div> */} <div className= "currentType"> <div className='currentType-icon'> {this.currentComponent} @@ -1727,7 +1728,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <div className="propertiesView-title" style={{ width: this.props.width }}> Properties </div> - <div className = "propertiesView-info" onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/')}> + <div className = "propertiesView-info" onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation//properties/')}> <GrCircleInformation/> </div> </div> diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index ad557e079..578ee1caa 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1416,14 +1416,18 @@ export namespace Doc { } export function setDocRangeFilter(container: Opt<Doc>, 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()); @@ -1437,6 +1441,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<Doc>, 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]); |
