diff options
-rw-r--r-- | src/client/views/nodes/DataVizBox/components/Chart.scss | 54 | ||||
-rw-r--r-- | src/client/views/nodes/DataVizBox/components/TableBox.tsx | 118 |
2 files changed, 157 insertions, 15 deletions
diff --git a/src/client/views/nodes/DataVizBox/components/Chart.scss b/src/client/views/nodes/DataVizBox/components/Chart.scss index 15d289abf..cf0007cfd 100644 --- a/src/client/views/nodes/DataVizBox/components/Chart.scss +++ b/src/client/views/nodes/DataVizBox/components/Chart.scss @@ -120,18 +120,62 @@ } } } -.select-buttons { +.tableBox-selectButtons { margin-top: 5px; margin-left: 25px; display: inline-block; - .selectTitle { - display: inline-block; - + padding: 2px; + .tableBox-selectTitle { + display: inline-flex; + flex-direction: row; } - .selectAll { + .tableBox-filtering { display: flex; flex-direction: row; float: right; margin-right: 10px; + .tableBox-filterAll { + min-width: 75px; + } + } +} + +.tableBox-filterPopup { + background: $light-gray; + position: absolute; + min-width: 235px; + top: 60px; + display: flex; + flex-direction: column; + align-items: flex-start; + z-index: 2; + padding: 7px; + border-radius: 5px; + margin: 3px; + .tableBox-filterPopup-selectColumn { + margin-top: 5px; + flex-direction: row; + .tableBox-filterPopup-selectColumn-each { + margin-left: 25px; + border-radius: 3px; + background: $light-gray; + } + } + .tableBox-filterPopup-setValue { + margin-top: 5px; + display: flex; + flex-direction: row; + .tableBox-filterPopup-setValue-each { + margin-right: 5px; + border-radius: 3px; + background: $light-gray; + } + .tableBox-filterPopup-setValue-input { + margin: 5px; + } + } + .tableBox-filterPopup-setFilter { + margin-top: 5px; + align-self: center; } } diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx index c9491da59..05429e82b 100644 --- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx +++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx @@ -12,6 +12,7 @@ import { ObservableReactComponent } from '../../../ObservableReactComponent'; import { DocumentView } from '../../DocumentView'; import { DataVizView } from '../DataVizBox'; import './Chart.scss'; +import { undoBatch } from '../../../../util/UndoManager'; const { default: { DATA_VIZ_TABLE_ROW_HEIGHT } } = require('../../../global/globalCssVariables.module.scss'); // prettier-ignore interface TableBoxProps { Document: Doc; @@ -36,7 +37,13 @@ interface TableBoxProps { export class TableBox extends ObservableReactComponent<TableBoxProps> { _inputChangedDisposer?: IReactionDisposer; _containerRef: HTMLDivElement | null = null; - @observable settingTitle: boolean = false; + + @observable settingTitle: boolean = false; // true when setting a title column + @observable hasRowsToFilter: boolean = false; // true when any rows are selected + @observable filtering: boolean = false; // true when the filtering menu is open + @observable filteringColumn: any = ""; // column to filter + @observable filteringType: string = "Value"; // "Value" or "Range" + filteringVal: any[] = ["", ""]; // value or range to filter the column with @observable _scrollTop = -1; @observable _tableHeight = 0; @@ -50,6 +57,8 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> { // if the tableData changes (ie., when records are selected by the parent (input) visulization), // then we need to remove any selected rows that are no longer part of the visualized dataset. this._inputChangedDisposer = reaction(() => this._tableData.slice(), this.filterSelectedRowsDown, { fireImmediately: true }); + const selected = NumListCast(this._props.layoutDoc.dataViz_selectedRows); + if (selected.length>0) this.hasRowsToFilter = true; this.handleScroll(); } componentWillUnmount() { @@ -65,9 +74,6 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> { @computed get parentViz() { return DocCast(this._props.Document.dataViz_parentViz); - // return LinkManager.Instance.getAllRelatedLinks(this._props.Document) // out of all links - // .filter(link => link.link_anchor_1 == this._props.Document.dataViz_parentViz) // get links where this chart doc is the target of the link - // .map(link => DocCast(link.link_anchor_1)); // then return the source of the link } @computed get columns() { @@ -116,6 +122,7 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> { } else selected?.push(rowId); } e.stopPropagation(); + this.hasRowsToFilter = (selected.length>0)? true : false; }; columnPointerDown = (e: React.PointerEvent, col: string) => { @@ -173,6 +180,88 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> { ); }; + /** + * These functions handle the filtering popup for when the "filter" button is pressed to select rows + */ + @undoBatch + filter = (e: any) => { + this._tableDataIds.forEach(rowID => { + if (this.filteringType=="Value"){ + if (this._props.records[rowID][this.filteringColumn]==this.filteringVal[0]) { + this.tableRowClick(e, rowID); + } + } + else { + if (this.filteringVal[0]<=this._props.records[rowID][this.filteringColumn] && this._props.records[rowID][this.filteringColumn]<=this.filteringVal[1]){ + this.tableRowClick(e, rowID); + } + } + }) + this.filtering = false; + this.filteringColumn = ""; + this.filteringVal = ["", ""]; + } + @action + setFilterColumn = (e:any) => { + this.filteringColumn = e.currentTarget.value; + } + @action + setFilterType = (e:any) => { + this.filteringType = e.currentTarget.value; + } + changeFilterValue = action((e: React.ChangeEvent<HTMLInputElement>) => { + this.filteringVal[0] = e.target.value; + }); + changeFilterRange0 = action((e: React.ChangeEvent<HTMLInputElement>) => { + this.filteringVal[0] = e.target.value; + }); + changeFilterRange1 = action((e: React.ChangeEvent<HTMLInputElement>) => { + this.filteringVal[1] = e.target.value; + }); + @computed get renderFiltering() { + if (this.filteringColumn==="") this.filteringColumn = this.columns[0]; + return ( + <div className="tableBox-filterPopup" style={{right: this._props.width*.05}}> + <div className="tableBox-filterPopup-selectColumn"> + Column: + <select className="tableBox-filterPopup-selectColumn-each" value={this.filteringColumn!=""? this.filteringColumn : this.columns[0]} onChange={e => this.setFilterColumn(e)}> + {this.columns.map(column => ( + <option className="" key={column} value={column}> {column} </option> + ))} + </select> + </div> + <div className="tableBox-filterPopup-setValue"> + <select className="tableBox-filterPopup-setValue-each" value={this.filteringType} onChange={e => this.setFilterType(e)}> + <option className="" key={"Value"} value={"Value"}> {"Value"} </option> + <option className="" key={"Range"} value={"Range"}> {"Range"} </option> + </select> + : + {this.filteringType=="Value"? + <input className="tableBox-filterPopup-setValue-input" defaultValue="" autoComplete="off" + onChange={this.changeFilterValue} onKeyDown={e => {e.stopPropagation();}} + type="text" placeholder="" id="search-input" + /> + : + <div> + <input className="tableBox-filterPopup-setValue-input" defaultValue="" autoComplete="off" + onChange={this.changeFilterRange0} onKeyDown={e => {e.stopPropagation();}} + type="text" placeholder="" id="search-input" style={{width: this._props.width*.15}} + /> + to + <input className="tableBox-filterPopup-setValue-input" defaultValue="" autoComplete="off" + onChange={this.changeFilterRange1} onKeyDown={e => {e.stopPropagation();}} + type="text" placeholder="" id="search-input" style={{width: this._props.width*.15}} + /> + </div> + } + </div> + <div className="tableBox-filterPopup-setFilter"> + <Button onClick={action((e) => this.filter(e))} text="Set Filter" type={Type.SEC} color={'black'} /> + </div> + </div> + ) + } + render() { if (this._tableData.length > 0) { return ( @@ -186,13 +275,22 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> { this._props.layoutDoc.dataViz_selectedRows = new List<number>(this._tableDataIds); } }}> - <div className="select-buttons"> - <div className="selectTitle"> - <Button onClick={action(() => (this.settingTitle = !this.settingTitle))} text="Select Title Column" type={Type.SEC} color={'black'} /> + <div className="tableBox-selectButtons"> + <div className="tableBox-selectTitle"> + <Button onClick={action(() => (this.settingTitle = !this.settingTitle))} text="Select Title Column" tooltip="TOOLTIP TEST YAY" type={Type.SEC} color={'black'} /> + </div> + <div className="tableBox-filtering"> + {this.filtering? this.renderFiltering : null} + <Button onClick={action(() => (this.filtering = !this.filtering))} text="Filter" type={Type.SEC} color={'black'} /> + <div className="tableBox-filterAll"> + {this.hasRowsToFilter? <Button onClick={action(() => { + this._props.layoutDoc.dataViz_selectedRows = new List<number>(); + this.hasRowsToFilter = false; })} text="Deselect All" type={Type.SEC} color={'black'} tooltip="Select rows to be displayed in any DataViz boxes dragged off of this one." /> + : <Button onClick={action(() => { + this._props.layoutDoc.dataViz_selectedRows = new List<number>(this._tableDataIds) + this.hasRowsToFilter = true; })} text="Select All" type={Type.SEC} color={'black'} tooltip="Select rows to be displayed in any DataViz boxes dragged off of this one." /> + } </div> - <div className="selectAll"> - <Button onClick={action(() => (this._props.layoutDoc.dataViz_selectedRows = new List<number>(this._tableDataIds)))} text="Select All" type={Type.SEC} color={'black'} /> - <Button onClick={action(() => (this._props.layoutDoc.dataViz_selectedRows = new List<number>()))} text="Deselect All" type={Type.SEC} color={'black'} /> </div> </div> <div |