aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/DataVizBox/components/TableBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/DataVizBox/components/TableBox.tsx')
-rw-r--r--src/client/views/nodes/DataVizBox/components/TableBox.tsx201
1 files changed, 183 insertions, 18 deletions
diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
index 53d1869d9..67e1c67bd 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 { undoable } from '../../../../util/UndoManager';
const { DATA_VIZ_TABLE_ROW_HEIGHT } = require('../../../global/globalCssVariables.module.scss'); // prettier-ignore
interface TableBoxProps {
Document: Doc;
@@ -37,6 +38,13 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> {
_inputChangedDisposer?: IReactionDisposer;
_containerRef: HTMLDivElement | null = null;
+ @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;
@observable _tableContainerHeight = 0;
@@ -49,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() {
@@ -64,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() {
@@ -115,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) => {
@@ -155,7 +163,8 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> {
},
emptyFunction,
action(e => {
- if (e.shiftKey) {
+ if (e.shiftKey || this.settingTitle) {
+ if (this.settingTitle) this.settingTitle = false;
if (this._props.titleCol == col) this._props.titleCol = '';
else this._props.titleCol = col;
this._props.selectTitleCol(this._props.titleCol);
@@ -170,6 +179,134 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> {
);
};
+ /**
+ * These functions handle the filtering popup for when the "filter" button is pressed to select rows
+ */
+ filter = undoable((e: any) => {
+ var start: any;
+ var end: any;
+ if (this.filteringType == 'Range') {
+ start = (this.filteringVal[0] as Number) ? Number(this.filteringVal[0]) : this.filteringVal[0];
+ end = (this.filteringVal[1] as Number) ? Number(this.filteringVal[1]) : this.filteringVal[0];
+ }
+
+ this._tableDataIds.forEach(rowID => {
+ if (this.filteringType == 'Value') {
+ if (this._props.records[rowID][this.filteringColumn] == this.filteringVal[0]) {
+ if (!NumListCast(this._props.layoutDoc.dataViz_selectedRows).includes(rowID)) {
+ this.tableRowClick(e, rowID);
+ }
+ }
+ } else {
+ let compare = this._props.records[rowID][this.filteringColumn];
+ if (compare as Number) compare = Number(compare);
+ if (start <= compare && compare <= end) {
+ if (!NumListCast(this._props.layoutDoc.dataViz_selectedRows).includes(rowID)) {
+ this.tableRowClick(e, rowID);
+ }
+ }
+ }
+ });
+ this.filtering = false;
+ this.filteringColumn = '';
+ this.filteringVal = ['', ''];
+ }, 'filter table');
+ @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 * 0.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 * 0.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 * 0.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 (
@@ -183,9 +320,39 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> {
this._props.layoutDoc.dataViz_selectedRows = new List<number>(this._tableDataIds);
}
}}>
- <div className="selectAll-buttons">
- <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 className="tableBox-selectButtons">
+ <div className="tableBox-selectTitle">
+ <Button onClick={action(() => (this.settingTitle = !this.settingTitle))} text="Select Title Column" 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>
</div>
<div
className={`tableBox-container ${this.columns[0]}`}
@@ -227,17 +394,15 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> {
: this._props.axes.lastElement() === col || (this._props.axes.length > 2 && this._props.axes[1] == col)
? 'darkblue'
: undefined,
- background:
- this._props.axes.slice().reverse().lastElement() === col
- ? '#E3fbdb'
- : this._props.axes.length > 2 && this._props.axes.lastElement() === col
- ? '#Fbdbdb'
- : this._props.axes.lastElement() === col || (this._props.axes.length > 2 && this._props.axes[1] == col)
- ? '#c6ebf7'
- : undefined,
- // blue: #ADD8E6
- // green: #E3fbdb
- // red: #Fbdbdb
+ background: this.settingTitle
+ ? 'lightgrey'
+ : this._props.axes.slice().reverse().lastElement() === col
+ ? '#E3fbdb'
+ : this._props.axes.length > 2 && this._props.axes.lastElement() === col
+ ? '#Fbdbdb'
+ : this._props.axes.lastElement() === col || (this._props.axes.length > 2 && this._props.axes[1] == col)
+ ? '#c6ebf7'
+ : undefined,
fontWeight: 'bolder',
border: '3px solid black',
}}