aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/views/nodes/DataVizBox/DataVizBox.scss4
-rw-r--r--src/client/views/nodes/DataVizBox/DataVizBox.tsx3
-rw-r--r--src/client/views/nodes/DataVizBox/components/Chart.scss25
-rw-r--r--src/client/views/nodes/DataVizBox/components/TableBox.scss22
-rw-r--r--src/client/views/nodes/DataVizBox/components/TableBox.tsx267
5 files changed, 183 insertions, 138 deletions
diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.scss b/src/client/views/nodes/DataVizBox/DataVizBox.scss
index 385ef5a1b..430446c06 100644
--- a/src/client/views/nodes/DataVizBox/DataVizBox.scss
+++ b/src/client/views/nodes/DataVizBox/DataVizBox.scss
@@ -1,9 +1,9 @@
.dataviz {
- overflow: scroll;
+ overflow: auto;
height: 100%;
width: 100%;
- .datatype-button{
+ .datatype-button {
display: flex;
flex-direction: row;
}
diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
index 8f32e2ba4..b9db5fe15 100644
--- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx
+++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
@@ -174,9 +174,6 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
) : (
<div
className="dataViz"
- style={{
- pointerEvents: this.props.isContentActive() === true ? "all" : "none"
- }}
onWheel={e => e.stopPropagation()}
ref={r =>
r?.addEventListener(
diff --git a/src/client/views/nodes/DataVizBox/components/Chart.scss b/src/client/views/nodes/DataVizBox/components/Chart.scss
index 50dfe7f05..3072d0907 100644
--- a/src/client/views/nodes/DataVizBox/components/Chart.scss
+++ b/src/client/views/nodes/DataVizBox/components/Chart.scss
@@ -6,10 +6,10 @@
margin-top: 10px;
overflow-y: visible;
- .graph{
+ .graph {
overflow: visible;
}
- .graph-title{
+ .graph-title {
align-items: center;
font-size: larger;
display: flex;
@@ -29,7 +29,7 @@
position: relative;
margin-bottom: -35px;
}
- .selected-data{
+ .selected-data {
align-items: center;
text-align: center;
display: flex;
@@ -44,10 +44,10 @@
stroke-width: 2px;
}
}
-
- .histogram-bar{
+
+ .histogram-bar {
outline: thin solid black;
- &.hover{
+ &.hover {
outline: 3px solid black;
outline-offset: -3px;
}
@@ -91,13 +91,22 @@
.tableBox {
display: flex;
flex-direction: column;
+ height: calc(100% - 40px); // bcz: hack 40px is the size of the button rows
+ .table {
+ height: 100%;
+ }
}
-.table-container{
+.table-container {
overflow: scroll;
margin: 5px;
margin-left: 25px;
margin-right: 10px;
margin-bottom: 0;
+ tr td {
+ height: 40px !important; // bcz: hack. you can't set a <tr> height directly, but you can set the height of all of it's <td>s. So this is the height of a tableBox row.
+ padding: 0 !important;
+ vertical-align: middle !important;
+ }
}
.selectAll-buttons {
display: flex;
@@ -106,4 +115,4 @@
margin-top: 5px;
margin-right: 10px;
float: right;
-} \ No newline at end of file
+}
diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.scss b/src/client/views/nodes/DataVizBox/components/TableBox.scss
deleted file mode 100644
index 1264d6a46..000000000
--- a/src/client/views/nodes/DataVizBox/components/TableBox.scss
+++ /dev/null
@@ -1,22 +0,0 @@
-.table {
- margin-top: 10px;
- margin-bottom: 10px;
- margin-left: 10px;
- margin-right: 10px;
-}
-
-.table-row {
- display: flex;
- flex-direction: row;
- justify-content: space-between;
- align-items: center;
- padding: 5px;
- border-bottom: 1px solid #ccc;
-}
-
-.table-container {
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
-} \ No newline at end of file
diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
index 4d6027ca4..dd13c5749 100644
--- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx
+++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
@@ -1,5 +1,5 @@
import { Button, Type } from 'browndash-components';
-import { action, computed, IReactionDisposer, reaction } from 'mobx';
+import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { Doc, Field, NumListCast } from '../../../../../fields/Doc';
@@ -31,6 +31,9 @@ interface TableBoxProps {
@observer
export class TableBox extends React.Component<TableBoxProps> {
+ @observable startID: number = 0;
+ @observable endID: number = 15;
+
_inputChangedDisposer?: IReactionDisposer;
componentDidMount() {
// if the tableData changes (ie., when records are selected by the parent (input) visulization),
@@ -67,8 +70,59 @@ export class TableBox extends React.Component<TableBoxProps> {
this.props.layoutDoc.dataViz_highlitedRows = new List<number>(highlighted.filter(rowId => this._tableDataIds.includes(rowId))); // filters through highlighted to remove guids that were removed in the incoming data
};
+ @action handleScroll = () => {
+ var container = document.getElementsByClassName("table-container");
+ var eachCell = document.getElementsByClassName("table-row");
+ if (eachCell.length==0 || container.length==0) return;
+
+ var useContainer;
+ if (container.length==1) useContainer = container[0];
+ else {
+ for (var i=0; i<container.length; i++){
+ if (container[i].classList.contains(this.columns[0])) useContainer = container[i];
+ }
+ }
+ var useCell;
+ if (eachCell.length==1) useCell = eachCell[0];
+ else {
+ for (var i=0; i<eachCell.length; i++){
+ if (eachCell[i].classList.contains(this.columns[0])) useCell = eachCell[i];
+ }
+ }
+ if (useCell && useContainer){
+ let atEnd = false;
+ // top
+ if (useContainer.scrollTop <= 10){
+ atEnd = true;
+ if (this.startID >= -1){
+ this.startID -= .001;
+ this.endID -= .001;
+ }
+ }
+ // bottom
+ else if (useContainer.scrollHeight / (useContainer.scrollTop + useContainer.getBoundingClientRect().height) < 1.1 && this.endID<=this._tableDataIds.length){
+ this.startID += .015;
+ this.endID += .015;
+ }
+ // regular scroll
+ else if (this.endID<=this._tableDataIds.length && !atEnd) {
+ let newStart = (useContainer.scrollTop / useCell.getBoundingClientRect().height ) ;
+ if (newStart<this.startID && this.startID>=-1){
+ this.startID -= .001;
+ this.endID -= .001; }
+ else if (newStart>this.startID) {
+ this.startID += .001;
+ this.endID += .001; }
+ }
+ }
+ else {
+ this.endID = this._tableDataIds.length - 1;
+ }
+ }
+
render() {
if (this._tableData.length > 0) {
+
return (
<div
className="tableBox"
@@ -84,13 +138,14 @@ export class TableBox extends React.Component<TableBoxProps> {
<Button onClick={action(() => (this.props.layoutDoc.dataViz_selectedRows = new List<number>()))} text="Deselect All" type={Type.SEC} color={'black'} />
</div>
<div
- className="table-container"
+ className={`table-container ${this.columns[0]}`}
style={{ height: this.props.height }}
ref={r =>
r?.addEventListener(
'wheel', // if scrollTop is 0, then don't let wheel trigger scroll on any container (which it would since onScroll won't be triggered on this)
(e: WheelEvent) => {
if (!r.scrollTop && e.deltaY <= 0) e.preventDefault();
+ this.handleScroll();
e.stopPropagation();
},
{ passive: false }
@@ -98,112 +153,118 @@ export class TableBox extends React.Component<TableBoxProps> {
}>
<table className="table">
<thead>
- <tr className="table-row">
- {this.columns.map(col => (
- <th
- key={this.columns.indexOf(col)}
- style={{
- color: this.props.axes.slice().reverse().lastElement() === col ? 'darkgreen' : this.props.axes.lastElement() === col ? 'darkred' : undefined,
- background: this.props.axes.slice().reverse().lastElement() === col ? '#E3fbdb' : this.props.axes.lastElement() === col ? '#Fbdbdb' : undefined,
- fontWeight: 'bolder',
- border: '3px solid black',
- }}
- onPointerDown={e => {
- const downX = e.clientX;
- const downY = e.clientY;
- setupMoveUpEvents(
- {},
- e,
- e => {
- // dragging off a column to create a brushed DataVizBox
- const sourceAnchorCreator = () => this.props.docView?.()!.rootDoc!;
- const targetCreator = (annotationOn: Doc | undefined) => {
- const embedding = Doc.MakeEmbedding(this.props.docView?.()!.rootDoc!);
- embedding._dataViz = DataVizView.TABLE;
- embedding._dataViz_axes = new List<string>([col, col]);
- embedding._dataViz_parentViz = this.props.rootDoc;
- embedding.annotationOn = annotationOn; //this.props.docView?.()!.rootDoc!;
- embedding.histogramBarColors = Field.Copy(this.props.layoutDoc.histogramBarColors);
- embedding.defaultHistogramColor = this.props.layoutDoc.defaultHistogramColor;
- embedding.pieSliceColors = Field.Copy(this.props.layoutDoc.pieSliceColors);
- return embedding;
- };
- if (this.props.docView?.() && !Utils.isClick(e.clientX, e.clientY, downX, downY, Date.now())) {
- DragManager.StartAnchorAnnoDrag(
- e.target instanceof HTMLElement ? [e.target] : [],
- new DragManager.AnchorAnnoDragData(this.props.docView()!, sourceAnchorCreator, targetCreator),
- downX,
- downY,
- {
- dragComplete: e => {
- if (!e.aborted && e.annoDragData && e.annoDragData.linkSourceDoc && e.annoDragData.dropDocument && e.linkDocument) {
- e.linkDocument.link_displayLine = true;
- e.linkDocument.link_matchEmbeddings = true;
- e.linkDocument.link_displayArrow = true;
- // e.annoDragData.linkSourceDoc.followLinkToggle = e.annoDragData.dropDocument.annotationOn === this.props.rootDoc;
- // e.annoDragData.linkSourceDoc.followLinkZoom = false;
- }
- },
- }
- );
- return true;
- }
- return false;
- },
- emptyFunction,
- action(e => {
- const newAxes = this.props.axes;
- if (newAxes.includes(col)) newAxes.splice(newAxes.indexOf(col), 1);
- else if (newAxes.length > 1) newAxes[1] = col;
- else newAxes.push(col);
- this.props.selectAxes(newAxes);
- })
- );
- }}>
- {col}
- </th>
- ))}
+ <tr >
+ {this.columns.map(col => {
+ if (this.startID>0) return;
+ return (
+ <th
+ key={this.columns.indexOf(col)}
+ style={{
+ color: this.props.axes.slice().reverse().lastElement() === col ? 'darkgreen' : this.props.axes.lastElement() === col ? 'darkred' : undefined,
+ background: this.props.axes.slice().reverse().lastElement() === col ? '#E3fbdb' : this.props.axes.lastElement() === col ? '#Fbdbdb' : undefined,
+ fontWeight: 'bolder',
+ border: '3px solid black',
+ }}
+ onPointerDown={e => {
+ const downX = e.clientX;
+ const downY = e.clientY;
+ setupMoveUpEvents(
+ {},
+ e,
+ e => {
+ // dragging off a column to create a brushed DataVizBox
+ const sourceAnchorCreator = () => this.props.docView?.()!.rootDoc!;
+ const targetCreator = (annotationOn: Doc | undefined) => {
+ const embedding = Doc.MakeEmbedding(this.props.docView?.()!.rootDoc!);
+ embedding._dataViz = DataVizView.TABLE;
+ embedding._dataViz_axes = new List<string>([col, col]);
+ embedding._dataViz_parentViz = this.props.rootDoc;
+ embedding.annotationOn = annotationOn; //this.props.docView?.()!.rootDoc!;
+ embedding.histogramBarColors = Field.Copy(this.props.layoutDoc.histogramBarColors);
+ embedding.defaultHistogramColor = this.props.layoutDoc.defaultHistogramColor;
+ embedding.pieSliceColors = Field.Copy(this.props.layoutDoc.pieSliceColors);
+ return embedding;
+ };
+ if (this.props.docView?.() && !Utils.isClick(e.clientX, e.clientY, downX, downY, Date.now())) {
+ DragManager.StartAnchorAnnoDrag(
+ e.target instanceof HTMLElement ? [e.target] : [],
+ new DragManager.AnchorAnnoDragData(this.props.docView()!, sourceAnchorCreator, targetCreator),
+ downX,
+ downY,
+ {
+ dragComplete: e => {
+ if (!e.aborted && e.annoDragData && e.annoDragData.linkSourceDoc && e.annoDragData.dropDocument && e.linkDocument) {
+ e.linkDocument.link_displayLine = true;
+ e.linkDocument.link_matchEmbeddings = true;
+ // e.annoDragData.linkSourceDoc.followLinkToggle = e.annoDragData.dropDocument.annotationOn === this.props.rootDoc;
+ // e.annoDragData.linkSourceDoc.followLinkZoom = false;
+ }
+ },
+ }
+ );
+ return true;
+ }
+ return false;
+ },
+ emptyFunction,
+ action(e => {
+ const newAxes = this.props.axes;
+ if (newAxes.includes(col)) newAxes.splice(newAxes.indexOf(col), 1);
+ else if (newAxes.length > 1) newAxes[1] = col;
+ else newAxes.push(col);
+ this.props.selectAxes(newAxes);
+ })
+ );
+ }}>
+ {col}
+ </th>
+ )}
+ )}
</tr>
</thead>
<tbody>
{this._tableDataIds
?.map(rowId => ({ record: this.props.records[rowId], rowId }))
- .map(({ record, rowId }) => (
- <tr
- key={rowId}
- className="table-row"
- onClick={action(e => {
- const highlited = Cast(this.props.layoutDoc.dataViz_highlitedRows, listSpec('number'), null);
- const selected = Cast(this.props.layoutDoc.dataViz_selectedRows, listSpec('number'), null);
- if (e.metaKey) {
- // highlighting a row
- if (highlited?.includes(rowId)) highlited.splice(highlited.indexOf(rowId), 1);
- else highlited?.push(rowId);
- if (!selected?.includes(rowId)) selected?.push(rowId);
- } else {
- // selecting a row
- if (selected?.includes(rowId)) {
- if (highlited?.includes(rowId)) highlited.splice(highlited.indexOf(rowId), 1);
- selected.splice(selected.indexOf(rowId), 1);
- } else selected?.push(rowId);
- }
- e.stopPropagation();
- })}
- style={{
- background: NumListCast(this.props.layoutDoc.dataViz_highlitedRows).includes(rowId) ? 'lightYellow' : NumListCast(this.props.layoutDoc.dataViz_selectedRows).includes(rowId) ? 'lightgrey' : '',
- width: '110%',
- }}>
- {this.columns.map(col => {
- // each cell
- const colSelected = this.props.axes.length > 1 ? this.props.axes[0] == col || this.props.axes[1] == col : this.props.axes.length > 0 ? this.props.axes[0] == col : false;
- return (
- <td key={this.columns.indexOf(col)} style={{ border: colSelected ? '3px solid black' : '1px solid black', fontWeight: colSelected ? 'bolder' : 'normal' }}>
- {record[col]}
- </td>
- );
- })}
- </tr>
- ))}
+ .map(({ record, rowId }) => {
+ if (this.startID<=rowId && rowId<=this.endID){
+ return (
+ <tr
+ key={rowId}
+ className={`table-row ${this.columns[0]}`}
+ onClick={action(e => {
+ const highlited = Cast(this.props.layoutDoc.dataViz_highlitedRows, listSpec('number'), null);
+ const selected = Cast(this.props.layoutDoc.dataViz_selectedRows, listSpec('number'), null);
+ if (e.metaKey) {
+ // highlighting a row
+ if (highlited?.includes(rowId)) highlited.splice(highlited.indexOf(rowId), 1);
+ else highlited?.push(rowId);
+ if (!selected?.includes(rowId)) selected?.push(rowId);
+ } else {
+ // selecting a row
+ if (selected?.includes(rowId)) {
+ if (highlited?.includes(rowId)) highlited.splice(highlited.indexOf(rowId), 1);
+ selected.splice(selected.indexOf(rowId), 1);
+ } else selected?.push(rowId);
+ }
+ e.stopPropagation();
+ })}
+ style={{
+ background: NumListCast(this.props.layoutDoc.dataViz_highlitedRows).includes(rowId) ? 'lightYellow' : NumListCast(this.props.layoutDoc.dataViz_selectedRows).includes(rowId) ? 'lightgrey' : '',
+ width: '110%',
+ }}>
+ {this.columns.map(col => {
+ // each cell
+ const colSelected = this.props.axes.length > 1 ? this.props.axes[0] == col || this.props.axes[1] == col : this.props.axes.length > 0 ? this.props.axes[0] == col : false;
+ return (
+ <td key={this.columns.indexOf(col)} style={{ border: colSelected ? '3px solid black' : '1px solid black', fontWeight: colSelected ? 'bolder' : 'normal' }}>
+ {record[col]}
+ </td>
+ );
+ })}
+ </tr>
+ )
+ }
+ })}
</tbody>
</table>
</div>