Compare commits
2 Commits
311180189f
...
73c30d7f8e
| Author | SHA1 | Date |
|---|---|---|
|
|
73c30d7f8e | |
|
|
b2cff623b7 |
|
|
@ -2,7 +2,11 @@
|
||||||
"tabList": [{
|
"tabList": [{
|
||||||
"tabTitle": "Tab 1",
|
"tabTitle": "Tab 1",
|
||||||
"fileName": "data.csv",
|
"fileName": "data.csv",
|
||||||
"colorColumn": "status"
|
"colorColumn": "status",
|
||||||
|
"colorMap" : {
|
||||||
|
"complicated":"red",
|
||||||
|
"single":"green"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tabTitle": "Tab 2",
|
"tabTitle": "Tab 2",
|
||||||
|
|
@ -25,5 +29,11 @@
|
||||||
"fileName": "data.csv",
|
"fileName": "data.csv",
|
||||||
"chartColumn": "status"
|
"chartColumn": "status"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"colorMaps" : {
|
||||||
|
"status" : {
|
||||||
|
"complicated":"red",
|
||||||
|
"single":"green"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import {
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import { Container, Title } from 'bloomer';
|
import { Container, Title } from 'bloomer';
|
||||||
const randomColor = require('randomcolor');
|
// const randomColor = require('randomcolor');
|
||||||
import * as Papa from 'papaparse';
|
import * as Papa from 'papaparse';
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -36,26 +36,30 @@ export class Chart extends React.Component<any, any> {
|
||||||
value: countMap[k],
|
value: countMap[k],
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const RADIAN = Math.PI / 180;
|
// const RADIAN = Math.PI / 180;
|
||||||
const renderCustomizedLabel = ({ cx, cy, midAngle, innerRadius, outerRadius, percent, index }:any) => {
|
// const renderCustomizedLabel = ({ cx, cy, midAngle, innerRadius, outerRadius, percent, index }:any) => {
|
||||||
const radius = innerRadius + (outerRadius - innerRadius) * 0.5;
|
// const radius = innerRadius + (outerRadius - innerRadius) * 0.5;
|
||||||
const x = cx + radius * Math.cos(-midAngle * RADIAN);
|
// const x = cx + radius * Math.cos(-midAngle * RADIAN);
|
||||||
const y = cy + radius * Math.sin(-midAngle * RADIAN);
|
// const y = cy + radius * Math.sin(-midAngle * RADIAN);
|
||||||
|
//
|
||||||
return (
|
// return (
|
||||||
<text x={x} y={y} fill="white" textAnchor='middle' dominantBaseline="central">
|
// <text x={x} y={y} fill="white" textAnchor='middle' dominantBaseline="central">
|
||||||
{chartData[index].name}
|
// {chartData[index].name}
|
||||||
</text>
|
// </text>
|
||||||
);
|
// );
|
||||||
};
|
// };
|
||||||
|
const colorMap = this.props.colorMap;
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Title isSize={4}>Plotting {_.capitalize(this.props.chartColumn)}</Title>
|
<Title isSize={4}>Plotting {_.capitalize(this.props.chartColumn)}</Title>
|
||||||
<ResponsiveContainer width="100%" height={200}>
|
<ResponsiveContainer width="100%" height={200}>
|
||||||
<PieChart>
|
<PieChart>
|
||||||
<Pie data={chartData} dataKey='value' outerRadius={100} label={renderCustomizedLabel} labelLine={false}>
|
<Pie data={chartData} dataKey='value' outerRadius={100} label={true} labelLine={false}>
|
||||||
{
|
{
|
||||||
chartData.map((_0, _1) => <Cell key={_1} fill={randomColor()} />)
|
chartData.map((_0, _1) => {
|
||||||
|
const color = _.get(colorMap, _0.name, 'gray');
|
||||||
|
return (<Cell key={_1} fill={color} />)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
</Pie>
|
</Pie>
|
||||||
<Tooltip />
|
<Tooltip />
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,21 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import * as _ from 'lodash';
|
|
||||||
import { Columns, Column } from 'bloomer';
|
import { Columns, Column } from 'bloomer';
|
||||||
import * as local from 'localforage';
|
|
||||||
import { Chart } from './Chart';
|
import { Chart } from './Chart';
|
||||||
|
|
||||||
export default class ChartLoader extends React.Component<any, any> {
|
export default class ChartLoader extends React.Component<any, any> {
|
||||||
constructor(props: any) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
chartList: []
|
|
||||||
}
|
|
||||||
fetch('/config.json')
|
|
||||||
.then((response) => response.text())
|
|
||||||
.then((jsonStr) => {
|
|
||||||
const jsonObj = JSON.parse(jsonStr);
|
|
||||||
const chartList = _.get<any>(jsonObj, 'chartList', []);
|
|
||||||
this.setState({ chartList });
|
|
||||||
local.setItem('config', jsonObj).catch((err: any) => {
|
|
||||||
console.error('error occurred when saving config', err);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
console.error('error occurred when loading config', e);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
|
const colorMaps = this.props.colorMaps;
|
||||||
return (
|
return (
|
||||||
<Columns>
|
<Columns>
|
||||||
{this.state.chartList.map((o: any, i: number) =>
|
{this.props.chartList.map((o: any, i: number) => {
|
||||||
|
const colorMap = colorMaps[o.chartColumn];
|
||||||
|
return (
|
||||||
<Column key={i} isSize={3}>
|
<Column key={i} isSize={3}>
|
||||||
<Chart csvFile={o.fileName} chartColumn={o.chartColumn} />
|
<Chart csvFile={o.fileName} chartColumn={o.chartColumn} colorMap={colorMap} />
|
||||||
</Column>
|
</Column>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
)}
|
)}
|
||||||
</Columns>
|
</Columns>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import {
|
||||||
Link
|
Link
|
||||||
} from 'react-router-dom';
|
} from 'react-router-dom';
|
||||||
import { Container, Navbar, NavbarItem, NavbarMenu, Section } from 'bloomer';
|
import { Container, Navbar, NavbarItem, NavbarMenu, Section } from 'bloomer';
|
||||||
|
import * as local from 'localforage';
|
||||||
import 'bulma/css/bulma.css';
|
import 'bulma/css/bulma.css';
|
||||||
import ServerTabLoader from './ServerTabLoader';
|
import ServerTabLoader from './ServerTabLoader';
|
||||||
import ChartLoader from './ChartLoader';
|
import ChartLoader from './ChartLoader';
|
||||||
|
|
@ -15,7 +16,32 @@ const navButton = (name: string, link: string) => (
|
||||||
|
|
||||||
const RedirectCharts = () => (<Redirect to='/charts' />);
|
const RedirectCharts = () => (<Redirect to='/charts' />);
|
||||||
|
|
||||||
const AppRoute = () => (
|
class AppRoute extends React.Component {
|
||||||
|
constructor(props: any) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
tabList:[],
|
||||||
|
chartList: [],
|
||||||
|
colorMaps:{}
|
||||||
|
}
|
||||||
|
fetch('/config.json')
|
||||||
|
.then((response) => response.text())
|
||||||
|
.then((jsonStr) => {
|
||||||
|
const jsonObj = JSON.parse(jsonStr);
|
||||||
|
this.setState({ ...jsonObj });
|
||||||
|
local.setItem('config', jsonObj).catch((err: any) => {
|
||||||
|
console.error('error occurred when saving config', err);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.error('error occurred when loading config', e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
const ConfiguredChart = () => (<ChartLoader {...this.state}/>);
|
||||||
|
const ConfiguredServerTab = () => (<ServerTabLoader {...this.state}/>);
|
||||||
|
return (
|
||||||
<Router>
|
<Router>
|
||||||
<div>
|
<div>
|
||||||
<Container isFluid={true} isMarginless={true} isFullWidth={true}>
|
<Container isFluid={true} isMarginless={true} isFullWidth={true}>
|
||||||
|
|
@ -28,10 +54,12 @@ const AppRoute = () => (
|
||||||
</Container>
|
</Container>
|
||||||
<Section isPaddingless={true}>
|
<Section isPaddingless={true}>
|
||||||
<Route exact={true} path="/" component={RedirectCharts} />
|
<Route exact={true} path="/" component={RedirectCharts} />
|
||||||
<Route path="/charts" component={ChartLoader} />
|
<Route path="/charts" component={ConfiguredChart} />
|
||||||
<Route path="/tables" component={ServerTabLoader} />
|
<Route path="/tables" component={ConfiguredServerTab} />
|
||||||
</Section>
|
</Section>
|
||||||
</div>
|
</div>
|
||||||
</Router>
|
</Router>
|
||||||
)
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
export default AppRoute
|
export default AppRoute
|
||||||
|
|
|
||||||
|
|
@ -1,75 +1,29 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import * as _ from 'lodash';
|
|
||||||
import ServerTable from './ServerTable';
|
import ServerTable from './ServerTable';
|
||||||
import { Tabs, TabList, TabPanel, Tab } from 'react-tabs';
|
import { Tabs, TabList, TabPanel, Tab } from 'react-tabs';
|
||||||
import { Hero, HeroBody } from 'bloomer';
|
import { Hero, HeroBody } from 'bloomer';
|
||||||
import * as local from 'localforage';
|
|
||||||
import './Tabs.css';
|
import './Tabs.css';
|
||||||
|
|
||||||
|
|
||||||
export default class ServerTabLoader extends React.Component<any, any> {
|
export default class ServerTabLoader extends React.Component<any, any> {
|
||||||
constructor(props: any) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
tabList: []
|
|
||||||
}
|
|
||||||
fetch('/config.json')
|
|
||||||
.then((response) => response.text())
|
|
||||||
.then((jsonStr) => {
|
|
||||||
const jsonObj = JSON.parse(jsonStr);
|
|
||||||
const tabList = _.get<any>(jsonObj, 'tabList', []);
|
|
||||||
this.setState({ tabList });
|
|
||||||
local.setItem('config', jsonObj).catch((err: any) => {
|
|
||||||
console.error('error occurred when saving config', err);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
console.error('error occurred when loading config', e);
|
|
||||||
});
|
|
||||||
// TODO: enable localstore to load config
|
|
||||||
// const onLocal = (config: any) => {
|
|
||||||
// if (config) {
|
|
||||||
// const tabList = _.get<any>(config, 'tabList', []);
|
|
||||||
// this.setState({ tabList });
|
|
||||||
// } else {
|
|
||||||
// fetch('/config.json')
|
|
||||||
// .then((response) => response.text())
|
|
||||||
// .then((jsonStr) => {
|
|
||||||
// const jsonObj = JSON.parse(jsonStr);
|
|
||||||
// const tabList = _.get<any>(jsonObj, 'tabList', []);
|
|
||||||
// this.setState({ tabList });
|
|
||||||
// local.setItem('config', jsonObj).then((val: any) => {
|
|
||||||
// console.log('saved to localstore ',val);
|
|
||||||
// }).catch((err:any) => {
|
|
||||||
// console.error('error occurred when saving config', err);
|
|
||||||
// });
|
|
||||||
// })
|
|
||||||
// .catch((e) => {
|
|
||||||
// this.setState({ message: e.stack, showMessage: true });
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// local.getItem('config').then(onLocal).catch((err: any) => {
|
|
||||||
// // This code runs if there were any errors
|
|
||||||
// console.error('error occurred when getting config from localstore', err);
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
return (
|
return (
|
||||||
<Hero isColor='light' isSize='large' isFullWidth={true} isFullHeight={true}>
|
<Hero isColor='light' isSize='large' isFullWidth={true} isFullHeight={true}>
|
||||||
<HeroBody isPaddingless={true} isDisplay='block'>
|
<HeroBody isPaddingless={true} isDisplay='block'>
|
||||||
<Tabs forceRenderTabPanel={true}>
|
<Tabs forceRenderTabPanel={true}>
|
||||||
<TabList>
|
<TabList>
|
||||||
{this.state.tabList.map((o: any, i: number) =>
|
{this.props.tabList.map((o: any, i: number) =>
|
||||||
(<Tab key={i}>{o.tabTitle}</Tab>)
|
(<Tab key={i}>{o.tabTitle}</Tab>)
|
||||||
)}
|
)}
|
||||||
</TabList>
|
</TabList>
|
||||||
{this.state.tabList.map((o: any, i: number) =>
|
{this.props.tabList.map((o: any, i: number) => {
|
||||||
(<TabPanel key={i}>
|
const colorMap = this.props.colorMaps[o.colorColumn];
|
||||||
<ServerTable csvFile={o.fileName} colorColumn={o.colorColumn} />
|
return (
|
||||||
|
<TabPanel key={i}>
|
||||||
|
<ServerTable csvFile={o.fileName} colorColumn={o.colorColumn} colorMap={colorMap} />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
)
|
);
|
||||||
|
}
|
||||||
)}
|
)}
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</HeroBody>
|
</HeroBody>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import * as React from 'react';
|
||||||
import { Tips } from "./Utils";
|
import { Tips } from "./Utils";
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import { Button } from 'bloomer';
|
import { Button } from 'bloomer';
|
||||||
const randomColor = require('randomcolor');
|
// const randomColor = require('randomcolor');
|
||||||
const reactcsv = require('react-csv');
|
const reactcsv = require('react-csv');
|
||||||
const CSVLink = reactcsv.CSVLink;
|
const CSVLink = reactcsv.CSVLink;
|
||||||
import * as Papa from 'papaparse';
|
import * as Papa from 'papaparse';
|
||||||
|
|
@ -19,8 +19,8 @@ export default class ServerTable extends React.Component<any, any> {
|
||||||
}
|
}
|
||||||
const loaded = (results: any) => {
|
const loaded = (results: any) => {
|
||||||
const local = this;
|
const local = this;
|
||||||
const colsUnique = _.keys(_.groupBy(results.data, (o: any) => _.get<any>(o, this.props.colorColumn)));
|
// const colsUnique = _.keys(_.groupBy(results.data, (o: any) => _.get<any>(o, this.props.colorColumn)));
|
||||||
const colColorMap = _.zipObject(colsUnique, _.map(colsUnique, () => randomColor()));
|
const colColorMap = this.props.colorMap; // _.zipObject(colsUnique, _.map(colsUnique, () => randomColor()));
|
||||||
local.setState({
|
local.setState({
|
||||||
headers: results.meta.fields,
|
headers: results.meta.fields,
|
||||||
data: results.data,
|
data: results.data,
|
||||||
|
|
@ -61,7 +61,7 @@ export default class ServerTable extends React.Component<any, any> {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
const colValue = _.get<any>(rowInfo.row, colorCol, '');
|
const colValue = _.get<any>(rowInfo.row, colorCol, '');
|
||||||
const colColor = _.get<any>(colColorMap, colValue, 'green');
|
const colColor = _.get<any>(colColorMap, colValue, 'white');
|
||||||
return {
|
return {
|
||||||
style: {
|
style: {
|
||||||
background: colColor
|
background: colColor
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue