Compare commits

..

2 Commits

Author SHA1 Message Date
Malar Kannan 73c30d7f8e made config load at root and updated color loading logic 2018-07-01 22:11:00 +05:30
Malar Kannan b2cff623b7 configurable color map for rows 2018-07-01 21:25:23 +05:30
6 changed files with 101 additions and 121 deletions

View File

@ -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"
}
}
} }

View File

@ -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 />

View File

@ -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) => {
<Column key={i} isSize={3}> const colorMap = colorMaps[o.chartColumn];
<Chart csvFile={o.fileName} chartColumn={o.chartColumn} /> return (
</Column> <Column key={i} isSize={3}>
<Chart csvFile={o.fileName} chartColumn={o.chartColumn} colorMap={colorMap} />
</Column>
);
}
)} )}
</Columns> </Columns>
) )

View File

@ -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,23 +16,50 @@ const navButton = (name: string, link: string) => (
const RedirectCharts = () => (<Redirect to='/charts' />); const RedirectCharts = () => (<Redirect to='/charts' />);
const AppRoute = () => ( class AppRoute extends React.Component {
<Router> constructor(props: any) {
<div> super(props);
<Container isFluid={true} isMarginless={true} isFullWidth={true}> this.state = {
<Navbar style={{ border: 'solid 1px #00D1B2', margin: '0' }}> tabList:[],
<NavbarMenu isActive={true}> chartList: [],
<NavbarItem >{navButton('Charts', '/charts')}</NavbarItem> colorMaps:{}
<NavbarItem>{navButton('Tables', '/tables')}</NavbarItem> }
</NavbarMenu> fetch('/config.json')
</Navbar> .then((response) => response.text())
</Container> .then((jsonStr) => {
<Section isPaddingless={true}> const jsonObj = JSON.parse(jsonStr);
<Route exact={true} path="/" component={RedirectCharts} /> this.setState({ ...jsonObj });
<Route path="/charts" component={ChartLoader} /> local.setItem('config', jsonObj).catch((err: any) => {
<Route path="/tables" component={ServerTabLoader} /> console.error('error occurred when saving config', err);
</Section> });
</div> })
</Router> .catch((e) => {
) console.error('error occurred when loading config', e);
});
}
public render() {
const ConfiguredChart = () => (<ChartLoader {...this.state}/>);
const ConfiguredServerTab = () => (<ServerTabLoader {...this.state}/>);
return (
<Router>
<div>
<Container isFluid={true} isMarginless={true} isFullWidth={true}>
<Navbar style={{ border: 'solid 1px #00D1B2', margin: '0' }}>
<NavbarMenu isActive={true}>
<NavbarItem >{navButton('Charts', '/charts')}</NavbarItem>
<NavbarItem>{navButton('Tables', '/tables')}</NavbarItem>
</NavbarMenu>
</Navbar>
</Container>
<Section isPaddingless={true}>
<Route exact={true} path="/" component={RedirectCharts} />
<Route path="/charts" component={ConfiguredChart} />
<Route path="/tables" component={ConfiguredServerTab} />
</Section>
</div>
</Router>
);
}
}
export default AppRoute export default AppRoute

View File

@ -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> <TabPanel key={i}>
) <ServerTable csvFile={o.fileName} colorColumn={o.colorColumn} colorMap={colorMap} />
</TabPanel>
);
}
)} )}
</Tabs> </Tabs>
</HeroBody> </HeroBody>

View File

@ -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