aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--package-lock.json83
-rw-r--r--package.json1
-rw-r--r--src/client/views/nodes/DataViz.tsx20
-rw-r--r--src/client/views/nodes/DataVizBox/ChartBox.tsx296
4 files changed, 276 insertions, 124 deletions
diff --git a/package-lock.json b/package-lock.json
index 7d34ec01f..731599c73 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4997,6 +4997,11 @@
"postcss-value-parser": "^3.3.0"
}
},
+ "css-unit-converter": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz",
+ "integrity": "sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA=="
+ },
"css-vendor": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz",
@@ -5280,6 +5285,11 @@
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
},
+ "decimal.js-light": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz",
+ "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg=="
+ },
"decode-uri-component": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
@@ -7509,8 +7519,7 @@
"eventemitter3": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
- "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
- "dev": true
+ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
},
"events": {
"version": "3.3.0",
@@ -7961,6 +7970,11 @@
"integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
"dev": true
},
+ "fast-equals": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-2.0.4.tgz",
+ "integrity": "sha512-caj/ZmjHljPrZtbzJ3kfH5ia/k4mTJe/qSiXAGzxZWRZgsgDV0cvNaQULqUX8t0/JVlzzEdYOwCN5DmzTxoD4w=="
+ },
"fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@@ -17857,6 +17871,14 @@
"resolved": "https://registry.npmjs.org/react-resizable-rotatable-draggable/-/react-resizable-rotatable-draggable-0.2.0.tgz",
"integrity": "sha512-F8TPx3z7/AcmRViySbYV3LpUWXFpHlGAmKmNcYMgPlS+h1eYFazRG3xYS8Z6e48hWY1EcCny/YNrwRNUrap8CQ=="
},
+ "react-resize-detector": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/react-resize-detector/-/react-resize-detector-7.1.2.tgz",
+ "integrity": "sha512-zXnPJ2m8+6oq9Nn8zsep/orts9vQv3elrpA+R8XTcW7DVVUJ9vwDwMXaBtykAYjMnkCIaOoK9vObyR7ZgFNlOw==",
+ "requires": {
+ "lodash": "^4.17.21"
+ }
+ },
"react-reveal": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/react-reveal/-/react-reveal-1.2.2.tgz",
@@ -17917,6 +17939,28 @@
}
}
},
+ "react-smooth": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-2.0.1.tgz",
+ "integrity": "sha512-Own9TA0GPPf3as4vSwFhDouVfXP15ie/wIHklhyKBH5AN6NFtdk0UpHBnonV11BtqDkAWlt40MOUc+5srmW7NA==",
+ "requires": {
+ "fast-equals": "^2.0.0",
+ "react-transition-group": "2.9.0"
+ },
+ "dependencies": {
+ "react-transition-group": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz",
+ "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==",
+ "requires": {
+ "dom-helpers": "^3.4.0",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2",
+ "react-lifecycles-compat": "^3.0.4"
+ }
+ }
+ }
+ },
"react-table": {
"version": "6.11.5",
"resolved": "https://registry.npmjs.org/react-table/-/react-table-6.11.5.tgz",
@@ -18091,6 +18135,32 @@
"resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz",
"integrity": "sha1-xYDXfvLPyHUrEySYBg3JeTp6wBw="
},
+ "recharts": {
+ "version": "2.1.12",
+ "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.1.12.tgz",
+ "integrity": "sha512-dAzEuc9AjM+IF0A33QzEdBEUnyGKJcGUPa0MYm0vd38P3WouQjrj2egBrCNInE7ZcQwN+z3MoT7Rw03u8nP9HA==",
+ "requires": {
+ "classnames": "^2.2.5",
+ "d3-interpolate": "^2.0.0",
+ "d3-scale": "^3.0.0",
+ "d3-shape": "^2.0.0",
+ "eventemitter3": "^4.0.1",
+ "lodash": "^4.17.19",
+ "react-is": "^16.10.2",
+ "react-resize-detector": "^7.1.2",
+ "react-smooth": "^2.0.1",
+ "recharts-scale": "^0.4.4",
+ "reduce-css-calc": "^2.1.8"
+ }
+ },
+ "recharts-scale": {
+ "version": "0.4.5",
+ "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz",
+ "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==",
+ "requires": {
+ "decimal.js-light": "^2.4.1"
+ }
+ },
"rechoir": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
@@ -18126,6 +18196,15 @@
"strip-indent": "^1.0.1"
}
},
+ "reduce-css-calc": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-2.1.8.tgz",
+ "integrity": "sha512-8liAVezDmUcH+tdzoEGrhfbGcP7nOV4NkGE3a74+qqvE7nt9i4sKLGBuZNOnpI4WiGksiNPklZxva80061QiPg==",
+ "requires": {
+ "css-unit-converter": "^1.1.1",
+ "postcss-value-parser": "^3.3.0"
+ }
+ },
"reduce-flatten": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz",
diff --git a/package.json b/package.json
index 488375b03..1e43390d8 100644
--- a/package.json
+++ b/package.json
@@ -283,6 +283,7 @@
"react-table": "^6.11.5",
"react-transition-group": "^4.4.2",
"readline": "^1.3.0",
+ "recharts": "^2.1.12",
"request": "^2.88.2",
"request-promise": "^4.2.6",
"reveal.js": "^4.3.0",
diff --git a/src/client/views/nodes/DataViz.tsx b/src/client/views/nodes/DataViz.tsx
deleted file mode 100644
index df4c8f937..000000000
--- a/src/client/views/nodes/DataViz.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import { observer } from 'mobx-react';
-import * as React from 'react';
-import { ViewBoxBaseComponent } from '../DocComponent';
-import './DataViz.scss';
-import { FieldView, FieldViewProps } from './FieldView';
-
-@observer
-export class DataVizBox extends ViewBoxBaseComponent<FieldViewProps>() {
- public static LayoutString(fieldKey: string) {
- return FieldView.LayoutString(DataVizBox, fieldKey);
- }
-
- render() {
- return (
- <div>
- <div>Hi</div>
- </div>
- );
- }
-}
diff --git a/src/client/views/nodes/DataVizBox/ChartBox.tsx b/src/client/views/nodes/DataVizBox/ChartBox.tsx
index 07f754637..42bd8a7f6 100644
--- a/src/client/views/nodes/DataVizBox/ChartBox.tsx
+++ b/src/client/views/nodes/DataVizBox/ChartBox.tsx
@@ -1,27 +1,17 @@
-import { observer } from "mobx-react";
-import * as React from "react";
-import { Doc } from "../../../../fields/Doc";
-import {
- Chart as ChartJS,
- CategoryScale,
- LinearScale,
- BarElement,
- Title,
- Tooltip,
- Legend,
- InteractionItem,
- PointElement,
- LineElement,
- } from 'chart.js';
- import { Bar, getDatasetAtEvent, getElementAtEvent, Line } from 'react-chartjs-2';
-import { ChartJSOrUndefined } from "react-chartjs-2/dist/types";
-import { action, computed, observable } from "mobx";
-import { Cast, StrCast } from "../../../../fields/Types";
-
+import { observer } from 'mobx-react';
+import * as React from 'react';
+import { Doc } from '../../../../fields/Doc';
+// import { Chart as ChartJS, CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend, InteractionItem, PointElement, LineElement } from 'chart.js';
+// import { Bar, getDatasetAtEvent, getElementAtEvent, Line } from 'react-chartjs-2';
+import { ChartJSOrUndefined } from 'react-chartjs-2/dist/types';
+import { action, computed, observable } from 'mobx';
+import { Cast, StrCast } from '../../../../fields/Types';
+import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';
+import { CategoricalChartState } from 'recharts/types/chart/generateCategoricalChart';
export interface ChartBoxProps {
rootDoc: Doc;
- pairs: {x: number, y:number}[];
+ pairs: { x: number; y: number }[];
}
export interface ChartJsData {
@@ -30,85 +20,127 @@ export interface ChartJsData {
label: string;
data: number[];
backgroundColor: string[];
- }[]
+ }[];
}
-ChartJS.register(
- CategoryScale,
- LinearScale,
- BarElement,
- Title,
- Tooltip,
- Legend,
- PointElement,
- LineElement
- );
-
+// ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend, PointElement, LineElement);
+
const primaryColor = 'rgba(53, 162, 235, 0.5)';
const selectedColor = 'rgba(255, 99, 132, 0.5)';
+const data = [
+ {
+ name: 'Page A',
+ uv: 4000,
+ pv: 2400,
+ amt: 2400,
+ },
+ {
+ name: 'Page B',
+ uv: 3000,
+ pv: 1398,
+ amt: 2210,
+ },
+ {
+ name: 'Page C',
+ uv: 2000,
+ pv: 9800,
+ amt: 2290,
+ },
+ {
+ name: 'Page D',
+ uv: 2780,
+ pv: 3908,
+ amt: 2000,
+ },
+ {
+ name: 'Page E',
+ uv: 1890,
+ pv: 4800,
+ amt: 2181,
+ },
+ {
+ name: 'Page F',
+ uv: 2390,
+ pv: 3800,
+ amt: 2500,
+ },
+ {
+ name: 'Page G',
+ uv: 3490,
+ pv: 4300,
+ amt: 2100,
+ },
+];
+
+export interface RechartData {
+ name: string | number;
+ y: number;
+}
+
@observer
export class ChartBox extends React.Component<ChartBoxProps> {
- private _chartRef: any = React.createRef<ChartJSOrUndefined<"bar", number[], string>>();
-
- @observable private _prevColor: string | undefined= undefined;
- @observable private _prevIndex: { dIndex: number, index: number} | undefined = undefined;
- @observable private _chartJsData: ChartJsData | undefined= undefined;
+ @observable private _chartData: RechartData[] = [];
@computed get currView() {
if (this.props.rootDoc._dataVizView) {
return StrCast(this.props.rootDoc._currChartView);
} else {
- return "table";
+ return 'table';
}
}
constructor(props: any) {
super(props);
if (!this.props.rootDoc._currChartView) {
- this.props.rootDoc._currChartView = "bar";
- }
- }
-
- @computed get options() {
- return {
- responsive: true,
- plugins: {
- legend: {
- position: 'top' as const,
- },
- title: {
- display: true,
- text: 'Bar Chart',
- },
- },
+ this.props.rootDoc._currChartView = 'bar';
}
}
@action
- generateChartJsData() {
+ generateChartData() {
if (this.props.rootDoc._chartData) {
- // parse the string into a json object
- this._chartJsData = JSON.parse(StrCast(this.props.rootDoc._chartData));
- this._prevColor = StrCast(this.props.rootDoc._prevColor);
- this._prevIndex = JSON.parse(StrCast(this.props.rootDoc._prevIndex));
+ this._chartData = JSON.parse(StrCast(this.props.rootDoc._chartData));
return;
}
- const labels = this.props.pairs.map(p => p.x);
- const dataset = {
- label: 'Dataset 1',
- data: this.props.pairs.map(p => p.y),
- backgroundColor: this.props.pairs.map(p => primaryColor),
- }
- const data = {
- labels,
- datasets: [dataset]
- };
- this._chartJsData = data;
+
+ // generate the chart data according to the RechartData type from the pairs prop
+ const chartData: RechartData[] = [];
+ this.props.pairs.forEach(pair => {
+ chartData.push({
+ name: pair.x,
+ y: pair.y,
+ });
+ });
+
+ this._chartData = chartData;
}
-
+
+ // @action
+ // generateChartJsData() {
+ // if (this.props.rootDoc._chartData) {
+ // // parse the string into a json object
+ // this._chartJsData = JSON.parse(StrCast(this.props.rootDoc._chartData));
+ // this._prevColor = StrCast(this.props.rootDoc._prevColor);
+ // this._prevIndex = JSON.parse(StrCast(this.props.rootDoc._prevIndex));
+ // return;
+ // }
+ // const labels = this.props.pairs.map(p => p.x);
+ // const dataset = {
+ // label: 'Dataset 1',
+ // data: this.props.pairs.map(p => p.y),
+ // backgroundColor: this.props.pairs.map(p => primaryColor),
+ // };
+ // const data = {
+ // labels,
+ // datasets: [dataset],
+ // };
+ // this._chartJsData = data;
+ // }
+
componentDidMount() {
- this.generateChartJsData();
+ // this.generateChartJsData();
+ this.generateChartData();
}
@action
@@ -117,46 +149,106 @@ export class ChartBox extends React.Component<ChartBoxProps> {
e.stopPropagation();
console.log(e.currentTarget.value);
this.props.rootDoc._currChartView = e.currentTarget.value.toLowerCase();
- }
+ };
- @action
- onClick = (e: any) => {
- e.preventDefault();
- if (getDatasetAtEvent(this._chartRef.current, e).length == 0) return;
- if (!this._chartJsData) return;
- if (this._prevIndex && this._prevColor) {
- this._chartJsData.datasets[this._prevIndex.dIndex].backgroundColor[this._prevIndex.index] = this._prevColor;
+ // @action
+ // onClick = (e: React.MouseEvent<HTMLCanvasElement, MouseEvent>) => {
+ // e.preventDefault();
+ // console.log(e);
+
+ // if (getDatasetAtEvent(this._chartRef.current, e).length == 0) return;
+ // if (!this._chartJsData) return;
+ // if (this._prevIndex && this._prevColor) {
+ // this._chartJsData.datasets[this._prevIndex.dIndex].backgroundColor[this._prevIndex.index] = this._prevColor;
+ // }
+
+ // const currSelected = getElementAtEvent(this._chartRef.current, e);
+ // // TODO - nda: the currSelected might not have the updated color variables so look into that
+ // this._currSelected = currSelected;
+ // const index = { datasetIndex: currSelected[0].datasetIndex, index: currSelected[0].index };
+ // this._prevIndex = { dIndex: index.datasetIndex, index: index.index };
+ // this._prevColor = this._chartJsData.datasets[index.datasetIndex].backgroundColor[index.index];
+ // this._chartJsData.datasets[index.datasetIndex].backgroundColor[index.index] = selectedColor;
+ // this._chartRef.current.update();
+ // // stringify this._chartJsData
+ // const strData = JSON.stringify(this._chartJsData);
+ // this.props.rootDoc._chartData = strData;
+ // this.props.rootDoc._prevColor = this._prevColor;
+ // this.props.rootDoc._prevIndex = JSON.stringify(this._prevIndex);
+ // };
+
+ onMouseMove = (e: CategoricalChartState) => {
+ console.log(e);
+
+ // pops up at 526 when it should be at 263
+ // at 100%scale it pops up at 526 but mouse shows 263 at 50% scale
+ if (e.chartX && e.chartY) {
+ e.chartX += 263;
+ e.chartY += 263;
}
+ // if (e.chartX && e.chartY) {
+ // e.chartX -= 200;
+ // e.chartY -= 200;
+ // }
+ };
- const currSelected = getElementAtEvent(this._chartRef.current, e);
- const index = { datasetIndex: currSelected[0].datasetIndex, index: currSelected[0].index };
- this._prevIndex = { dIndex: index.datasetIndex, index: index.index };
- this._prevColor = this._chartJsData.datasets[index.datasetIndex].backgroundColor[index.index];
- this._chartJsData.datasets[index.datasetIndex].backgroundColor[index.index] = selectedColor;
- this._chartRef.current.update();
- // stringify this._chartJsData
- const strData = JSON.stringify(this._chartJsData);
- this.props.rootDoc._chartData = strData;
- this.props.rootDoc._prevColor = this._prevColor;
- this.props.rootDoc._prevIndex = JSON.stringify(this._prevIndex);
+ handleDotClick = (e: any) => {
+ console.log(e);
+ };
+
+ // handleTextClick = (e: any) => {
+ // console.log(e);
+ // }
+
+ @computed get reLineChart() {
+ return (
+ <ResponsiveContainer width="80%" height="80%">
+ <LineChart
+ width={500}
+ height={300}
+ data={this._chartData}
+ margin={{
+ top: 5,
+ right: 30,
+ left: 20,
+ bottom: 5,
+ }}
+ onMouseDown={e => console.log(e)}
+ onMouseMove={e => this.onMouseMove(e)}>
+ <CartesianGrid strokeDasharray="3 3" />
+ <XAxis dataKey="name" onMouseDown={e => console.log(e)} />
+ <YAxis />
+ <Tooltip />
+ <Legend />
+ <Line type="monotone" dataKey="y" stroke="#8884d8" activeDot={{ r: 8, onClick: this.handleDotClick }} />
+ {/* <Line type="monotone" dataKey="uv" stroke="#82ca9d" /> */}
+ </LineChart>
+ </ResponsiveContainer>
+ );
}
render() {
- if (this.props.pairs && this._chartJsData) {
+ if (this.props.pairs && this._chartData.length > 0) {
return (
<div>
<div>
- {this.props.rootDoc._currChartView == "line" ?
- (<Line ref={this._chartRef} options={this.options} data={this._chartJsData} onClick={(e) => this.onClick(e)} />) :
- (<Bar ref={this._chartRef} options={this.options} data={this._chartJsData} onClick={(e) => this.onClick(e)} />)
- }
+ {/*{this.props.rootDoc._currChartView == 'line' ? (
+ <Line ref={this._chartRef} options={this.options} data={this._chartJsData} onClick={e => this.onClick(e)} />
+ ) : (
+ <Bar ref={this._chartRef} options={this.options} data={this._chartJsData} onClick={e => this.onClick(e)} />
+ )} */}
+ {this.reLineChart}
</div>
- <button onClick={(e) => this.onClickChangeChart(e)} value="line">Line</button>
- <button onClick={(e) => this.onClickChangeChart(e)} value="bar">Bar</button>
+ <button onClick={e => this.onClickChangeChart(e)} value="line">
+ Line
+ </button>
+ <button onClick={e => this.onClickChangeChart(e)} value="bar">
+ Bar
+ </button>
</div>
- )
+ );
} else {
- return <div></div>
+ return <div></div>;
}
}
-} \ No newline at end of file
+}