aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/DataVizBox/DataVizBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/DataVizBox/DataVizBox.tsx')
-rw-r--r--src/client/views/nodes/DataVizBox/DataVizBox.tsx171
1 files changed, 86 insertions, 85 deletions
diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
index c07ab5ba1..f9f241234 100644
--- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx
+++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
@@ -1,3 +1,4 @@
+import { Toggle, ToggleType, Type } from 'browndash-components';
import { action, computed, ObservableMap } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
@@ -9,12 +10,11 @@ import { Docs } from '../../../documents/Documents';
import { ViewBoxAnnotatableComponent } from '../../DocComponent';
import { FieldView, FieldViewProps } from '../FieldView';
import { PinProps } from '../trails';
+import { Histogram } from './components/Histogram';
import { LineChart } from './components/LineChart';
+import { PieChart } from './components/PieChart';
import { TableBox } from './components/TableBox';
import './DataVizBox.scss';
-import { Histogram } from './components/Histogram';
-import { PieChart } from './components/PieChart';
-import { Toggle, ToggleType, Type } from 'browndash-components';
export enum DataVizView {
TABLE = 'table',
@@ -29,19 +29,29 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
return FieldView.LayoutString(DataVizBox, fieldStr);
}
- // all data
- static pairSet = new ObservableMap<string, { [key: string]: string }[]>();
- @computed.struct get pairs() {
- return DataVizBox.pairSet.get(CsvCast(this.rootDoc[this.fieldKey]).url.href);
- }
+ // all datasets that have been retrieved from the server stored as a map from the dataset url to an array of records
+ static dataset = new ObservableMap<string, { [key: string]: string }[]>();
+ private _vizRenderer: LineChart | Histogram | PieChart | undefined;
- private _chartRenderer: LineChart | Histogram | PieChart | undefined;
+ // all CSV records in the dataset
+ @computed.struct get records() {
+ return DataVizBox.dataset.get(CsvCast(this.rootDoc[this.fieldKey]).url.href);
+ }
- // current displayed chart type
+ // currently chosen visualization type: line, pie, histogram, table
@computed get dataVizView(): DataVizView {
return StrCast(this.layoutDoc._dataViz, 'table') as DataVizView;
}
+ @computed get dataUrl() {
+ return Cast(this.dataDoc[this.fieldKey], CsvField);
+ }
+ @computed.struct get axes() {
+ return StrListCast(this.layoutDoc.dataViz_axes);
+ }
+
+ selectAxes = (axes: string[]) => (this.layoutDoc.dataViz_axes = new List<string>(axes));
+
@action // pinned / linked anchor doc includes selected rows, graph titles, and graph colors
restoreView = (data: Doc) => {
const changedView = this.dataVizView !== data.config_dataViz && (this.layoutDoc._dataViz = data.config_dataViz);
@@ -55,7 +65,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
this.layoutDoc['_' + key] = data[key];
}
});
- const func = () => this._chartRenderer?.restoreView(data);
+ const func = () => this._vizRenderer?.restoreView(data);
if (changedView || changedAxes) {
setTimeout(func, 100);
return true;
@@ -65,7 +75,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
getAnchor = (addAsAnnotation?: boolean, pinProps?: PinProps) => {
const anchor = !pinProps
? this.rootDoc
- : this._chartRenderer?.getAnchor(pinProps) ??
+ : this._vizRenderer?.getAnchor(pinProps) ??
Docs.Create.ConfigDocument({
// when we clear selection -> we should have it so chartBox getAnchor returns undefined
// this is for when we want the whole doc (so when the chartBox getAnchor returns without a marker)
@@ -86,87 +96,78 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
return anchor;
};
- @computed.struct get axes() {
- return StrListCast(this.layoutDoc.dataViz_axes);
+ componentDidMount() {
+ this.props.setContentView?.(this);
+ if (!DataVizBox.dataset.has(CsvCast(this.rootDoc[this.fieldKey]).url.href)) this.fetchData();
}
- selectAxes = (axes: string[]) => (this.layoutDoc.dataViz_axes = new List<string>(axes));
+
+ fetchData = () => {
+ DataVizBox.dataset.set(CsvCast(this.rootDoc[this.fieldKey]).url.href, []); // assign temporary dataset as a lock to prevent duplicate server requests
+ fetch('/csvData?uri=' + this.dataUrl?.url.href) //
+ .then(res => res.json().then(action(res => !res.errno && DataVizBox.dataset.set(CsvCast(this.rootDoc[this.fieldKey]).url.href, res))));
+ };
// toggles for user to decide which chart type to view the data in
- @computed get selectView() {
+ renderVizView = () => {
const width = this.props.PanelWidth() * 0.9;
const height = (this.props.PanelHeight() - 32) /* height of 'change view' button */ * 0.9;
const margin = { top: 10, right: 25, bottom: 75, left: 45 };
- if (!this.pairs) return 'no data';
- switch (this.dataVizView) {
- case DataVizView.TABLE:
- return <TableBox layoutDoc={this.layoutDoc} pairs={this.pairs} axes={this.axes} height={height} width={width} margin={margin} rootDoc={this.rootDoc} docView={this.props.DocumentView} selectAxes={this.selectAxes} />;
- case DataVizView.LINECHART:
- return (
- <LineChart
- layoutDoc={this.layoutDoc}
- 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}
- />
- );
- case DataVizView.HISTOGRAM:
- return (
- <Histogram
- layoutDoc={this.layoutDoc}
- 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}
- />
- );
- case DataVizView.PIECHART:
- return (
- <PieChart
- layoutDoc={this.layoutDoc}
- 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}
- />
- );
+ if (this.records) {
+ switch (this.dataVizView) {
+ case DataVizView.TABLE:
+ return <TableBox layoutDoc={this.layoutDoc} records={this.records} axes={this.axes} height={height} width={width} margin={margin} rootDoc={this.rootDoc} docView={this.props.DocumentView} selectAxes={this.selectAxes} />;
+ case DataVizView.LINECHART:
+ return (
+ <LineChart
+ layoutDoc={this.layoutDoc}
+ ref={r => (this._vizRenderer = r ?? undefined)}
+ height={height}
+ width={width}
+ fieldKey={this.fieldKey}
+ margin={margin}
+ rootDoc={this.rootDoc}
+ axes={this.axes}
+ records={this.records}
+ dataDoc={this.dataDoc}
+ />
+ );
+ case DataVizView.HISTOGRAM:
+ return (
+ <Histogram
+ layoutDoc={this.layoutDoc}
+ ref={r => (this._vizRenderer = r ?? undefined)}
+ height={height}
+ width={width}
+ fieldKey={this.fieldKey}
+ margin={margin}
+ rootDoc={this.rootDoc}
+ axes={this.axes}
+ records={this.records}
+ dataDoc={this.dataDoc}
+ />
+ );
+ case DataVizView.PIECHART:
+ return (
+ <PieChart
+ layoutDoc={this.layoutDoc}
+ ref={r => (this._vizRenderer = r ?? undefined)}
+ height={height}
+ width={width}
+ fieldKey={this.fieldKey}
+ margin={margin}
+ rootDoc={this.rootDoc}
+ axes={this.axes}
+ records={this.records}
+ dataDoc={this.dataDoc}
+ />
+ );
+ }
}
- }
-
- @computed get dataUrl() {
- return Cast(this.dataDoc[this.fieldKey], CsvField);
- }
-
- componentDidMount() {
- this.props.setContentView?.(this);
- this.fetchData();
- if (!this.layoutDoc._dataViz) this.layoutDoc._dataViz = this.dataVizView;
- }
-
- fetchData() {
- if (DataVizBox.pairSet.has(CsvCast(this.rootDoc[this.fieldKey]).url.href)) return;
- DataVizBox.pairSet.set(CsvCast(this.rootDoc[this.fieldKey]).url.href, []);
- fetch('/csvData?uri=' + this.dataUrl?.url.href) //
- .then(res => res.json().then(action(res => !res.errno && DataVizBox.pairSet.set(CsvCast(this.rootDoc[this.fieldKey]).url.href, res))));
- }
+ return 'no data/visualization';
+ };
render() {
- return !this.pairs?.length ? (
+ return !this.records?.length ? (
// displays how to get data into the DataVizBox if its empty
<div className="start-message">To create a DataViz box, either import / drag a CSV file into your canvas or copy a data table and use the command 'ctrl + p' to bring the data table to your canvas.</div>
) : (
@@ -189,7 +190,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
<Toggle text={'HISTOGRAM'} toggleType={ToggleType.BUTTON} type={Type.SEC} color={'black'} onClick={e => (this.layoutDoc._dataViz = DataVizView.HISTOGRAM)} toggleStatus={this.layoutDoc._dataViz == DataVizView.HISTOGRAM} />
<Toggle text={'PIE CHART'} toggleType={ToggleType.BUTTON} type={Type.SEC} color={'black'} onClick={e => (this.layoutDoc._dataViz = DataVizView.PIECHART)} toggleStatus={this.layoutDoc._dataViz == DataVizView.PIECHART} />
</div>
- {this.selectView}
+ {this.renderVizView()}
</div>
);
}