Wednesday, 18 July 2018

react chart2 bar series

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);


----------------------------------------------------

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);

------------------------------------

reference:
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