aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/views/nodes/DataVizBox/DataVizBox.tsx31
-rw-r--r--src/client/views/nodes/DataVizBox/components/LineChart.tsx33
-rw-r--r--src/client/views/nodes/DataVizBox/components/TableBox.tsx43
-rw-r--r--src/client/views/nodes/trails/PresBox.tsx7
4 files changed, 79 insertions, 35 deletions
diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
index e279a1262..0ce589a13 100644
--- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx
+++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
@@ -1,7 +1,8 @@
import { action, computed, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Doc } from '../../../../fields/Doc';
+import { Doc, StrListCast } from '../../../../fields/Doc';
+import { List } from '../../../../fields/List';
import { Cast, NumCast, StrCast } from '../../../../fields/Types';
import { CsvField } from '../../../../fields/URLField';
import { Docs } from '../../../documents/Documents';
@@ -26,7 +27,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
// 2 ways of doing it
// @observable private pairs: { [key: string]: number | string | undefined }[] = [];
// @observable private pairs: { [key: string]: FieldResult }[] = [];
- @observable private pairs: { x: number; y: number }[] = [];
+ @observable private pairs: { [key: string]: string }[] = [];
private _chartRenderer: LineChart | undefined;
// // another way would be store a schema that defines the type of data we are expecting from an imported doc
@@ -51,16 +52,17 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
// TODO: nda - use onmousedown and onmouseup when dragging and changing height and width to update the height and width props only when dragging stops
@computed get dataVizView(): DataVizView {
- return StrCast(this.rootDoc._dataVizView, 'table') as DataVizView;
+ return StrCast(this.layoutDoc._dataVizView, 'table') as DataVizView;
}
@action
restoreView = (data: Doc) => {
- const changed = this.dataVizView !== data.presDataVizView && (this.rootDoc._dataVizView = data.presDataVizView);
+ const changedView = this.dataVizView !== data.presDataVizView && (this.layoutDoc._dataVizView = data.presDataVizView);
+ const changedAxes = this.axes.join('') !== StrListCast(data.presDataVizAxes).join('') && (this.layoutDoc._dataVizAxes = new List<string>(StrListCast(data.presDataVizAxes)));
const func = () => this._chartRenderer?.restoreView(data);
- if (changed) {
+ if (changedView || changedAxes) {
setTimeout(func, 100);
- return changed ? true : false;
+ return true;
}
return func() ?? false;
};
@@ -75,26 +77,27 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
});
anchor.presDataVizView = this.dataVizView;
+ anchor.presDataVizAxes = this.axes.length ? new List<string>(this.axes) : undefined;
this.addDocument(anchor);
return anchor;
};
+ @computed.struct get axes() {
+ return StrListCast(this.layoutDoc.dataVizAxes);
+ }
+ selectAxes = (axes: string[]) => (this.layoutDoc.dataVizAxes = new List<string>(axes));
+
@computed get selectView() {
const width = NumCast(this.rootDoc._width) * 0.9;
const height = (this.props.PanelHeight() - 32) /* height of 'change view' button */ * 0.9;
const margin = { top: 10, right: 50, bottom: 50, left: 50 };
// prettier-ignore
switch (this.dataVizView) {
- case DataVizView.TABLE: return <TableBox pairs={this.pairs} />;
- case DataVizView.LINECHART: return <LineChart ref={r => (this._chartRenderer = r ?? undefined)} height={height} width={width} fieldKey={this.fieldKey} margin={margin} rootDoc={this.rootDoc} pairs={this.pairs} dataDoc={this.dataDoc} />;
+ case DataVizView.TABLE: return <TableBox pairs={this.pairs} axes={this.axes} selectAxes={this.selectAxes}/>;
+ case DataVizView.LINECHART: return <LineChart ref={r => (this._chartRenderer = r ?? undefined)} height={height} width={width} fieldKey={this.fieldKey} margin={margin} rootDoc={this.rootDoc} axes={this.axes} pairs={this.pairs} dataDoc={this.dataDoc} />;
}
}
-
- @computed get pairVals() {
- return fetch('/csvData?uri=' + this.dataUrl?.url.href).then(res => res.json());
- }
-
@computed get dataUrl() {
return Cast(this.dataDoc[this.fieldKey], CsvField);
}
@@ -113,7 +116,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@action changeViewHandler(e: React.MouseEvent<HTMLButtonElement>) {
e.preventDefault();
e.stopPropagation();
- this.rootDoc._dataVizView = this.dataVizView === DataVizView.TABLE ? DataVizView.LINECHART : DataVizView.TABLE;
+ this.layoutDoc._dataVizView = this.dataVizView === DataVizView.TABLE ? DataVizView.LINECHART : DataVizView.TABLE;
}
render() {
diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx
index 313164691..2357b7c69 100644
--- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx
+++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx
@@ -4,6 +4,7 @@ import * as React from 'react';
// import d3
import * as d3 from 'd3';
import { Doc, DocListCast } from '../../../../../fields/Doc';
+import { List } from '../../../../../fields/List';
import { listSpec } from '../../../../../fields/Schema';
import { Cast } from '../../../../../fields/Types';
import { Docs } from '../../../../documents/Documents';
@@ -32,7 +33,8 @@ export interface LineChartData {
}
export interface LineChartProps {
rootDoc: Doc;
- pairs: { x: number; y: number }[];
+ axes: string[];
+ pairs: { [key: string]: any }[];
width: number;
height: number;
dataDoc: Doc;
@@ -67,8 +69,13 @@ export class LineChart extends React.Component<LineChartProps> {
Array.from(Object.keys(this._disposers)).forEach(key => this._disposers[key]());
}
componentDidMount = () => {
+ this._disposers.chartdata = reaction(
+ () => this.props.axes.slice(),
+ axes => axes.length > 1 && this.generateChartData(),
+ { fireImmediately: true }
+ );
this._disposers.chartData = reaction(
- () => ({ dataSet: this._lineChartData?.dataSet, w: this.props.width, h: this.props.height }),
+ () => ({ dataSet: this._lineChartData?.dataSet, axes: this.props.axes.slice(), w: this.props.width, h: this.props.height }),
vals => {
if (vals.dataSet) {
this._rangeVals = minMaxRange(vals.dataSet);
@@ -89,16 +96,15 @@ export class LineChart extends React.Component<LineChartProps> {
},
{ fireImmediately: true }
);
- this.generateChartData();
};
@action
generateChartData() {
this._lineChartData = {
- xLabel: 'x',
- yLabel: 'y',
+ xLabel: this.props.axes[0],
+ yLabel: this.props.axes[1],
// TODO: nda - add actual support for multiple sets of data
- dataSet: [this.props.pairs?.map(pair => ({ x: pair.x, y: pair.y }))],
+ dataSet: [this.props.pairs?.map(pair => ({ x: Number(pair[this.props.axes[0]]), y: Number(pair[this.props.axes[1]]) }))],
};
}
@@ -129,12 +135,17 @@ export class LineChart extends React.Component<LineChartProps> {
// loop through and remove any annotations that no longer exist
}
+ @action
restoreView = (data: Doc) => {
- const coords = Cast(data.presDataViz, listSpec('number'), null);
- if ((coords && this._currSelected?.x !== coords[0]) || this._currSelected?.y !== coords[1]) {
+ const coords = Cast(data.presDataVizSelection, listSpec('number'), null);
+ if (coords?.length > 1 && (this._currSelected?.x !== coords[0] || this._currSelected?.y !== coords[1])) {
this.setCurrSelected(coords[0], coords[1]);
return true;
}
+ if (this._currSelected) {
+ this._currSelected = undefined;
+ return true;
+ }
return false;
};
@@ -143,7 +154,8 @@ export class LineChart extends React.Component<LineChartProps> {
const anchor = Docs.Create.TextanchorDocument({
title: 'line doc selection' + this._currSelected?.x,
});
- PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), dataviz: this._currSelected ? [this._currSelected.x, this._currSelected.y] : undefined } }, this.props.dataDoc);
+ PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this.props.dataDoc);
+ anchor.presDataVizSelection = this._currSelected ? new List<number>([this._currSelected.x, this._currSelected.y]) : undefined;
return anchor;
};
@@ -277,9 +289,10 @@ export class LineChart extends React.Component<LineChartProps> {
};
render() {
+ const selectedPt = this._currSelected ? `x: ${this._currSelected.x} y: ${this._currSelected.y}` : 'none';
return (
<div ref={this._lineChartRef} className="chart-container">
- <span>Curr Selected: {this._currSelected ? `x: ${this._currSelected.x} y: ${this._currSelected.y}` : 'none'}</span>
+ <span> {this.props.axes.length < 2 ? 'first use table view to select two axes to plot' : `Curr Selected: ${selectedPt}`}</span>
</div>
);
}
diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
index 28114036f..adefe90cd 100644
--- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx
+++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
@@ -1,28 +1,59 @@
-import { action, computed, observable } from 'mobx';
+import { action, computed } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
+import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../../../Utils';
interface TableBoxProps {
- pairs: { x: number; y: number }[];
+ pairs: { [key: string]: any }[];
+ selectAxes: (axes: string[]) => void;
+ axes: string[];
}
+@observer
export class TableBox extends React.Component<TableBoxProps> {
+ @computed get columns() {
+ return this.props.pairs.length ? Array.from(Object.keys(this.props.pairs[0])) : [];
+ }
render() {
return (
<div className="table-container">
<table className="table">
<thead>
<tr className="table-row">
- <th>x</th>
- <th>y</th>
+ {this.columns.map(col => (
+ <th
+ style={{ color: this.props.axes.slice().reverse().lastElement() === col ? 'green' : this.props.axes.lastElement() === col ? 'red' : undefined, fontWeight: this.props.axes.includes(col) ? 'bolder' : 'normal' }}
+ onPointerDown={e =>
+ setupMoveUpEvents(
+ {},
+ e,
+ returnFalse,
+ 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[0] = col;
+ }
+ this.props.selectAxes(newAxes);
+ })
+ )
+ }>
+ {col}
+ </th>
+ ))}
</tr>
</thead>
<tbody>
{this.props.pairs?.map(p => {
return (
<tr className="table-row">
- <td>{p.x}</td>
- <td>{p.y}</td>
+ {this.columns.map(col => (
+ <td>{p[col]}</td>
+ ))}
</tr>
);
})}
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 0e22ea3b1..3589a9065 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -492,10 +492,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
changed = true;
}
}
- if (!pinDataTypes && activeItem.presDataViz !== undefined) {
- if (bestTargetView?.ComponentView?.restoreView?.(activeItem)) {
- changed = true;
- }
+ if (bestTargetView?.ComponentView?.restoreView?.(activeItem)) {
+ changed = true;
}
if (pinDataTypes?.scrollable || (!pinDataTypes && activeItem.presViewScroll !== undefined)) {
@@ -654,7 +652,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
if (pinProps.pinData.viewType) pinDoc.presViewType = targetDoc._viewType;
if (pinProps.pinData.filters) pinDoc.presDocFilters = ObjectField.MakeCopy(targetDoc.docFilters as ObjectField);
if (pinProps.pinData.pivot) pinDoc.presPivotField = targetDoc._pivotField;
- if (pinProps.pinData.dataviz) pinDoc.presDataViz = new List<number>(pinProps.pinData.dataviz);
if (pinProps.pinData.pannable) {
pinDoc.presPanX = NumCast(targetDoc._panX);
pinDoc.presPanY = NumCast(targetDoc._panY);