From 3b6b673cf1fd1e951c28210983d0b1d6176fc013 Mon Sep 17 00:00:00 2001
From: srichman333 <sarah_n_richman@brown.edu>
Date: Mon, 26 Feb 2024 00:57:44 -0500
Subject: select title col ui

---
 .../views/nodes/DataVizBox/components/TableBox.tsx  | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

(limited to 'src/client/views/nodes/DataVizBox/components/TableBox.tsx')

diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
index 1b239b5e5..c9491da59 100644
--- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx
+++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
@@ -36,6 +36,7 @@ interface TableBoxProps {
 export class TableBox extends ObservableReactComponent<TableBoxProps> {
     _inputChangedDisposer?: IReactionDisposer;
     _containerRef: HTMLDivElement | null = null;
+    @observable settingTitle: boolean = false;
 
     @observable _scrollTop = -1;
     @observable _tableHeight = 0;
@@ -155,7 +156,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);
@@ -184,9 +186,14 @@ 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="select-buttons">
+                        <div className="selectTitle">
+                            <Button onClick={action(() => (this.settingTitle = !this.settingTitle))} text="Select Title Column" type={Type.SEC} color={'black'} />
+                            </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
                         className={`tableBox-container ${this.columns[0]}`}
@@ -223,12 +230,10 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> {
                                                 color: this._props.axes.slice().reverse().lastElement() === col ? 'darkgreen' 
                                                     : (this._props.axes.length>2 && this._props.axes.lastElement() === col) ? 'darkred' 
                                                     : (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' 
+                                                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,
-                                                // blue: #ADD8E6
-                                                // green: #E3fbdb
-                                                // red: #Fbdbdb
                                                 fontWeight: 'bolder',
                                                 border: '3px solid black',
                                             }}
-- 
cgit v1.2.3-70-g09d2


From 8fc97eb6e093d4217f28919bf836425b75fdfea3 Mon Sep 17 00:00:00 2001
From: srichman333 <sarah_n_richman@brown.edu>
Date: Sun, 10 Mar 2024 14:00:08 -0400
Subject: filter tables

---
 .../views/nodes/DataVizBox/components/Chart.scss   |  54 +++++++++-
 .../views/nodes/DataVizBox/components/TableBox.tsx | 118 +++++++++++++++++++--
 2 files changed, 157 insertions(+), 15 deletions(-)

(limited to 'src/client/views/nodes/DataVizBox/components/TableBox.tsx')

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
-- 
cgit v1.2.3-70-g09d2


From 789e0d35e14f5fec7ef885daf3d61fa389117825 Mon Sep 17 00:00:00 2001
From: srichman333 <sarah_n_richman@brown.edu>
Date: Wed, 13 Mar 2024 19:02:56 -0400
Subject: keeping rows selected fix

---
 src/client/views/nodes/DataVizBox/components/TableBox.tsx | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

(limited to 'src/client/views/nodes/DataVizBox/components/TableBox.tsx')

diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
index 05429e82b..a0d8ecc6f 100644
--- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx
+++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
@@ -188,12 +188,16 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> {
         this._tableDataIds.forEach(rowID => {
             if (this.filteringType=="Value"){
                 if (this._props.records[rowID][this.filteringColumn]==this.filteringVal[0]) {
-                    this.tableRowClick(e, rowID);
+                    if (!NumListCast(this._props.layoutDoc.dataViz_selectedRows).includes(rowID)) {
+                        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);
+                    if (!NumListCast(this._props.layoutDoc.dataViz_selectedRows).includes(rowID)) {
+                        this.tableRowClick(e, rowID);
+                    }
                 }
             }
         })
-- 
cgit v1.2.3-70-g09d2


From 4c4ab22252aba8f08d8a384e2bd0c6696db9b43b Mon Sep 17 00:00:00 2001
From: srichman333 <sarah_n_richman@brown.edu>
Date: Sun, 31 Mar 2024 13:22:48 -0400
Subject: range

---
 src/client/views/nodes/DataVizBox/components/TableBox.tsx | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

(limited to 'src/client/views/nodes/DataVizBox/components/TableBox.tsx')

diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
index a0d8ecc6f..26e1eeeff 100644
--- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx
+++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
@@ -185,6 +185,13 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> {
      */
     @undoBatch
     filter = (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]) {
@@ -194,7 +201,9 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> {
                 }
             }
             else {
-                if (this.filteringVal[0]<=this._props.records[rowID][this.filteringColumn] && this._props.records[rowID][this.filteringColumn]<=this.filteringVal[1]){ 
+                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);
                     }
@@ -281,7 +290,7 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> {
                     }}>
                     <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'} />
+                            <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}
-- 
cgit v1.2.3-70-g09d2

