project link: https://chuanshuoge1-react-chart3.herokuapp.com/
top chart, bottom table
add new month
update
--src
--App.js
--App.css
--Charts
--bubbleCharts.js
--columnChart.js
--pieChart.js
--package.json
package.json
{"name": "react-chart-2",
"version": "0.1.0",
"private": true,
"dependencies": {
"@material-ui/core": "^1.4.0",
"@material-ui/icons": "^1.1.0",
"bootstrap": "^4.1.2",
"react": "^16.4.1",
"react-dom": "^16.4.1",
"react-router-dom": "^4.3.1",
"react-scripts": "1.1.4",
"react-vis": "^1.10.3",
"reactstrap": "^6.3.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
----------------------------------------------
App.js
import React, { Component } from 'react';
import './App.css';
import { Switch, Route, Link } from 'react-router-dom';
import { withStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Tabs from '@material-ui/core/Tabs';
import Tab from '@material-ui/core/Tab';
import BubbleChartIcon from '@material-ui/icons/BubbleChart';
import PieChartIcon from '@material-ui/icons/PieChart';
import InsertChartIcon from '@material-ui/icons/InsertChart';
import TimelineIcon from '@material-ui/icons/Timeline';
import BubbleChart from './charts/bubbleChart';
import ColumnChart from './charts/columnChart';
import PieChart from './charts/pieChart';
import WhiskerChart from './charts/whiskerChart';
const styles = theme => ({
root: {
flexGrow: 1,
backgroundColor: theme.palette.background.paper,
},
});
class App extends Component {
constructor(props) {
super(props);
this.state = {
tabNumber:0,
};
}
handleTabChange = (event, value) => {
this.setState({ tabNumber: value });
};
render() {
const { classes } = this.props;
const { tabNumber } = this.state;
return (
<div className={classes.root}>
<AppBar position="static" >
<Tabs value={tabNumber} onChange={this.handleTabChange}>
<Tab label={<Link to='/' className="my-link-color">Chart Series</Link>} />
<Tab label={<Link to='/stock' className="my-link-color"><TimelineIcon /></Link>} />
<Tab label={<Link to='/pie' className="my-link-color"><PieChartIcon /></Link>} />
<Tab label={<Link to='/bubble' className="my-link-color"><BubbleChartIcon /></Link>} />
<Tab label={<Link to='/column' className="my-link-color"><InsertChartIcon /></Link>} />
</Tabs>
</AppBar>
<Switch>
<Route exact path='/' component={BubbleChart} />
<Route path='/bubble' component={BubbleChart} />
<Route path='/pie' component={PieChart} />
<Route path='/column' component={ColumnChart} />
<Route path='/stock' component={WhiskerChart} />
</Switch>
</div>
);
}
}
export default withStyles(styles)(App);
import './App.css';
import { Switch, Route, Link } from 'react-router-dom';
import { withStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Tabs from '@material-ui/core/Tabs';
import Tab from '@material-ui/core/Tab';
import BubbleChartIcon from '@material-ui/icons/BubbleChart';
import PieChartIcon from '@material-ui/icons/PieChart';
import InsertChartIcon from '@material-ui/icons/InsertChart';
import TimelineIcon from '@material-ui/icons/Timeline';
import BubbleChart from './charts/bubbleChart';
import ColumnChart from './charts/columnChart';
import PieChart from './charts/pieChart';
import WhiskerChart from './charts/whiskerChart';
const styles = theme => ({
root: {
flexGrow: 1,
backgroundColor: theme.palette.background.paper,
},
});
class App extends Component {
constructor(props) {
super(props);
this.state = {
tabNumber:0,
};
}
handleTabChange = (event, value) => {
this.setState({ tabNumber: value });
};
render() {
const { classes } = this.props;
const { tabNumber } = this.state;
return (
<div className={classes.root}>
<AppBar position="static" >
<Tabs value={tabNumber} onChange={this.handleTabChange}>
<Tab label={<Link to='/' className="my-link-color">Chart Series</Link>} />
<Tab label={<Link to='/stock' className="my-link-color"><TimelineIcon /></Link>} />
<Tab label={<Link to='/pie' className="my-link-color"><PieChartIcon /></Link>} />
<Tab label={<Link to='/bubble' className="my-link-color"><BubbleChartIcon /></Link>} />
<Tab label={<Link to='/column' className="my-link-color"><InsertChartIcon /></Link>} />
</Tabs>
</AppBar>
<Switch>
<Route exact path='/' component={BubbleChart} />
<Route path='/bubble' component={BubbleChart} />
<Route path='/pie' component={PieChart} />
<Route path='/column' component={ColumnChart} />
<Route path='/stock' component={WhiskerChart} />
</Switch>
</div>
);
}
}
export default withStyles(styles)(App);
----------------------------------------------------
App.css
.my-link-color {
color: white;
text-decoration: none;
}
.my-link-color:hover {
color: cyan;
text-decoration: none;
}
my-link-color:focus {
color: gold;
text-decoration: none;
}
.my-table-header{
color:white;
background-color:black;
}
.deleteIcon{}
.deleteIcon:hover{
cursor:pointer;
}
.my-subTitle{
width:300px;
text-align:center;
}
------------------------------------
columnChart.js
import React, { Component } from 'react';
import '../App.css';
import '../../node_modules/react-vis/dist/style.css';
import { Table } from 'reactstrap';
import TextField from '@material-ui/core/TextField';
import { withStyles } from '@material-ui/core/styles';
import MenuItem from '@material-ui/core/MenuItem';
import DeleteIcon from '@material-ui/icons/Delete';
import {
XYPlot,
XAxis,
YAxis,
VerticalGridLines,
HorizontalGridLines,
VerticalBarSeries,
LabelSeries,
} from 'react-vis';
const styles = theme => ({
textField: {
margin: 0,
width: 100,
},
row: {
display: 'flex',
justifyContent: 'center',
margin: 0,
},
});
class ColumnChart extends Component {
constructor(props) {
super(props);
this.state = {
data:
[
{ x: 1, y: 0.3 },
{ x: 2, y: 0.33 },
{ x: 3, y: 0.28 },
{ x: 4, y: 0.35, label: 'maxxxxxx' },
],
};
}
handleXChange(value, index) {
const dataLength = this.state.data.length;
const oldProperty = this.state.data[index];
//check if it is an update or add request
const newProperty = {
x: value,
y: index < dataLength ? oldProperty.y : null,
label: index < dataLength ? oldProperty.label : null,
}
const newData = [...this.state.data];
newData.splice(index, 1, newProperty);
this.setState({ data: newData });
}
handleYChange(value, index) {
const dataLength = this.state.data.length;
const oldProperty = this.state.data[index];
const newProperty = {
x: oldProperty.x,
y: parseFloat(value),
label: oldProperty.label,
}
const newData = [...this.state.data];
newData.splice(index, 1, newProperty);
this.setState({ data: newData });
}
handleLabelChange(value, index) {
const oldProperty = this.state.data[index];
const newProperty = {
x: oldProperty.x,
y: oldProperty.y,
label: value,
}
const newData = [...this.state.data];
newData.splice(index, 1, newProperty);
this.setState({ data: newData });
}
handleDelete(index) {
const newData = [...this.state.data];
newData.splice(index, 1);
this.setState({ data: newData });
}
render() {
const { classes } = this.props;
const selectedMonth = this.state.data.map((item, index) => { return item.x })
const barData = [...this.state.data].sort((a, b) => { return a.x - b.x });
const labelData = barData.map((item, index) => {
return {
x: item.x, y: item.y, label: item.label,
yOffset: -50, rotation: -80, style: { fontSize: 14 }
}
});
return (
<div>
<XYPlot width={300} height={300} xDomain={[0, 12]} yDomain={[0.2, 0.45]}>
<VerticalGridLines />
<HorizontalGridLines />
<XAxis tickFormat={x => monthShort[x]} tickLabelAngle={-90}
tickValues={[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]} />
<YAxis title="$/KWH" />
<VerticalBarSeries data={barData} />
<LabelSeries
data={labelData} />
</XYPlot>
<Table bordered hover size="sm">
<thead className="my-table-header">
<tr>
<th>Month</th>
<th>$/KWH</th>
<th>Comment</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{
this.state.data.map((item, index) =>
<tr key={index}>
<td>
<TextField
select
className={classes.textField}
value={selectedMonth[index]}
onChange={(e) => this.handleXChange(e.target.value, index)}
SelectProps={{
MenuProps: {
className: classes.textField,
},
}}
>
{monthShort.map((item, index) => (
<MenuItem key={index} value={index}
disabled={selectedMonth.includes(index)}>
<div className={classes.row}>
{item}
</div>
</MenuItem>
))}
</TextField>
</td>
<td>
<TextField
required
onChange={(e) => this.handleYChange(e.target.value, index)}
value={item.y}
type="number"
className={classes.textField}
/>
</td>
<td>
<TextField
onChange={(e) => this.handleLabelChange(e.target.value, index)}
value={item.label}
className={classes.textField}
/>
</td>
<td>
<DeleteIcon className="deleteIcon"
onClick={() => this.handleDelete(index)} />
</td>
</tr>
)
}
{/*-----------add new month----------*/}
<tr>
<td>
<TextField
select
label="Add new"
className={classes.textField}
onChange={(e) => this.handleXChange(e.target.value, this.state.data.length)}
SelectProps={{
MenuProps: {
className: classes.textField,
},
}}
>
{monthShort.map((item, index) => (
<MenuItem key={index} value={index}
disabled={selectedMonth.includes(index)}>
<div className={classes.row}>
{item}
</div>
</MenuItem>
))}
</TextField>
</td>
<td></td>
<td></td>
</tr>
</tbody>
</Table>
</div>
);
}
}
const monthShort = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
export default withStyles(styles)(ColumnChart);
------------------------------------
https://material-ui.com/demos/tabs/
https://uber.github.io/react-vis/documentation/series-reference/label-series
https://github.com/uber/react-vis/blob/master/showcase/axes/custom-axes.js
https://github.com/uber/react-vis/blob/master/showcase/plot/scatterplot.js
https://github.com/uber/react-vis/blob/master/showcase/legends/searchable-discrete-color.js
No comments:
Post a Comment