Skip to content
This repository has been archived by the owner on Jun 4, 2024. It is now read-only.

Commit

Permalink
ChartEditor: WIP
Browse files Browse the repository at this point in the history
Closes #350
  • Loading branch information
n-riesco committed Mar 13, 2018
1 parent 80590c1 commit d963467
Show file tree
Hide file tree
Showing 5 changed files with 1,141 additions and 45 deletions.
24 changes: 8 additions & 16 deletions app/components/Settings/Preview/Preview.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {Tab, Tabs, TabList, TabPanel} from 'react-tabs';

import SQLTable from './sql-table.jsx';
import CodeEditorField from './CodeEditorField.react.js';
import ChartEditor from './ChartEditor.react.js';
import ChartEditor from './chart-editor.jsx';
import ApacheDrillPreview from './ApacheDrillPreview.js';
import S3Preview from './S3Preview.js';

Expand Down Expand Up @@ -365,30 +365,22 @@ class Preview extends Component {
<div>
<Tabs forceRenderTabPanel={true}>
<TabList>
<Tab>Chart</Tab>
<Tab>Table</Tab>
<Tab>Chart</Tab>
<Tab>Export</Tab>
</TabList>

<TabPanel>
<ChartEditor
<TabPanel
style={{fontFamily: "'Ubuntu Mono', courier, monospace", marginTop: '20px'}}
>
<SQLTable
rows={rows}
columnNames={columnNames}
plotJSON={plotJSON}
updateProps={newProps => {
updatePreview({'chartEditor': R.merge(
chartEditorState,
newProps
)});
}}
{...chartEditorState}
/>
</TabPanel>

<TabPanel
style={{fontFamily: "'Ubuntu Mono', courier, monospace", marginTop: '20px'}}
>
<SQLTable
<TabPanel>
<ChartEditor
rows={rows}
columnNames={columnNames}
/>
Expand Down
134 changes: 134 additions & 0 deletions app/components/Settings/Preview/chart-editor.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import React from 'react';
import PropTypes from 'prop-types';

import plotly from 'plotly.js/dist/plotly';
import createPlotComponent from 'react-plotly.js/factory';
import PlotlyEditor from 'react-chart-editor';
import 'react-chart-editor/lib/react-chart-editor.css';

const Plot = createPlotComponent(plotly);

export default class ChartEditor extends React.Component {
static propTypes = {
columnNames: PropTypes.array,
rows: PropTypes.array
}

/**
* ChartEditor displays a Plotly.js chart using the query results
*
* @param {object} props - Component properties
*
* @param {Array} props.columnNames - Array of column names
* @param {Array.<Array>} props.rows - Array of rows
*/
constructor(props) {
super(props);

this.computeDerivedProps();

/**
* @member {object} state - Component state
* @property {object} state.gd - Graph div
* @property {number} state.revision - Revision number
*/
this.state = {
gd: {},
revision: 0
};

/**
* Increment revision counter
* @returns {undefined}
*/
this.onEditorUpdate = () => {
this.setState(({revision: prevRevision}) => ({revision: prevRevision + 1}));
};

/**
* Updates graph div
* @param {object} gd - Graph div
* @returns {undefined}
*/
this.onPlotUpdate = (gd) => {
this.setState({gd});
};
}

computeDerivedProps() {
/**
* @member {object} dataSources - Create a data source per column (used by <PlotlyEditor>)
*/
this.dataSources = {};
this.props.columnNames.forEach(name => {
this.dataSources[name] = [];
});
this.props.rows.forEach(row => {
row.forEach((v, i) => {
const columnName = this.props.columnNames[i];
this.dataSources[columnName].push(v);
});
});

/**
* @member {Array.<object>} dataSourceOptions - Assign a label to each data source (used by <PlotlyEditor>)
*/
this.dataSourceOptions = this.props.columnNames.map(name => ({value: name, label: name}));
}

componentWillReceiveProps(newProps) {
// Did columnNames change?
const {columnNames} = this.props;
const {columnNames: newColumnNames} = newProps;

let isEqual = (columnNames.length === newColumnNames.length);
for (let i = 0; isEqual && (i < columnNames); i++) {
isEqual = isEqual && (columnNames[i] === newColumnNames[i]);
}

// If it did, update the derived props
if (!isEqual) {
this.computeDerivedProps();
}
}

render() {
const {gd, revision} = this.state;
const {data, layout} = gd;
const config = {editable: true};

return (
<div>
<div style={{
float: 'left',
width: 466
}}>
<PlotlyEditor
graphDiv={gd}
onUpdate={this.onEditorUpdate}
dataSources={this.dataSources}
dataSourceOptions={this.dataSourceOptions}
plotly={plotly}
/>
</div>
<div style={{
float: 'right',
height: 400,
width: 'calc(-466px + 100%)'
}}>
<Plot
debug
useResizeHandler
config={config}
data={data}
layout={layout}
onUpdate={this.onPlotUpdate}
onInitialized={this.onPlotUpdate}
revision={revision}
style={{width: '100%', height: '100%'}}
/>
</div>
</div>
);
}
}
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -187,12 +187,16 @@
"query-string": "^5.0.1",
"ramda": "^0.21.0",
"react": "^16.2.0",
"react-chart-editor": "^0.11.1",
"react-codemirror": "^1.0.0",
"react-cookies": "^0.1.0",
"react-data-grid": "^3.0.11",
"react-data-grid-addons": "^3.0.11",
"react-dnd": "^2.5.4",
"react-dnd-html5-backend": "^2.5.4",
"react-dom": "^16.2.0",
"react-immutable-proptypes": "^2.1.0",
"react-plotly.js": "^1.7.0",
"react-plotlyjs": "^0.4.4",
"react-redux": "^5.0.7",
"react-router": "^3.2.1",
Expand Down Expand Up @@ -228,8 +232,6 @@
"papaparse": "^4.3.7",
"pg": "^4.5.5",
"pg-hstore": "^2.3.2",
"react-data-grid": "^3.0.11",
"react-data-grid-addons": "^3.0.11",
"restify": "^4.3.2",
"sequelize": "^3.30.4",
"source-map-support": "^0.5.0",
Expand Down
7 changes: 7 additions & 0 deletions webpack.config.base.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ export default {
loader: 'babel-loader'
}],
exclude: /node_modules/
}, {
test: /\.css$/,
use: [{
loader: 'style-loader'
}, {
loader: 'css-loader'
}]
}]
},
output: {
Expand Down
Loading

0 comments on commit d963467

Please sign in to comment.