Compare commits
11 Commits
73c30d7f8e
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| ef3b9935a8 | |||
| 502121b536 | |||
| 4039a74fd7 | |||
|
|
b3358023f1 | ||
|
|
dc9c0d5e59 | ||
|
|
6bdb8b6174 | ||
|
|
97e628c4e1 | ||
|
|
b02c090d03 | ||
|
|
2dcb19c8ee | ||
|
|
2aae9ee455 | ||
|
|
0dcad337ed |
3
.env
Normal file
3
.env
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
GENERATE_SOURCEMAP=false
|
||||||
|
REACT_APP_API_HOST="http://localhost:5000/test/"
|
||||||
|
REACT_APP_API_DIR="/test/"
|
||||||
2
.env.development
Normal file
2
.env.development
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
REACT_APP_API_HOST="http://localhost:3000/"
|
||||||
|
REACT_APP_API_DIR="/"
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -7,7 +7,7 @@
|
|||||||
.LSOverride
|
.LSOverride
|
||||||
|
|
||||||
# Icon must end with two \r
|
# Icon must end with two \r
|
||||||
Icon
|
Icon
|
||||||
|
|
||||||
# Thumbnails
|
# Thumbnails
|
||||||
._*
|
._*
|
||||||
@@ -66,6 +66,7 @@ build/Release
|
|||||||
# Dependency directories
|
# Dependency directories
|
||||||
node_modules/
|
node_modules/
|
||||||
jspm_packages/
|
jspm_packages/
|
||||||
|
build/
|
||||||
|
|
||||||
# Typescript v1 declaration files
|
# Typescript v1 declaration files
|
||||||
typings/
|
typings/
|
||||||
|
|||||||
4
public/.htaccess
Normal file
4
public/.htaccess
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
Options -MultiViews
|
||||||
|
RewriteEngine On
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
RewriteRule ^ index.html [QSA,L]
|
||||||
@@ -2,11 +2,7 @@
|
|||||||
"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,15 +21,31 @@
|
|||||||
"fileName": "data.csv"
|
"fileName": "data.csv"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"chartList":[{
|
"chartList": [{
|
||||||
|
"chartTitle": "Status Plot",
|
||||||
|
"fileName": "data.csv",
|
||||||
|
"chartColumn": "status"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fileName": "data.csv",
|
||||||
|
"chartColumn": "age"
|
||||||
|
}, {
|
||||||
|
"chartTitle": "Another Status Plot",
|
||||||
|
"fileName": "data.csv",
|
||||||
|
"chartColumn": "status"
|
||||||
|
}, {
|
||||||
|
"chartTitle": "Yet Another Status Plot",
|
||||||
|
"fileName": "data.csv",
|
||||||
|
"chartColumn": "status"
|
||||||
|
}, {
|
||||||
"fileName": "data.csv",
|
"fileName": "data.csv",
|
||||||
"chartColumn": "status"
|
"chartColumn": "status"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"colorMaps" : {
|
"colorMaps": {
|
||||||
"status" : {
|
"status": {
|
||||||
"complicated":"red",
|
"complicated": "red",
|
||||||
"single":"green"
|
"single": "green"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
src/App.css
12
src/App.css
@@ -23,8 +23,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.navbar-item:hover {
|
.navbar-item:hover {
|
||||||
background-color: #f0f0f0;
|
background-color: rgba(10, 10, 10, .1);
|
||||||
color: #3273dc;
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* body {
|
||||||
|
font-family: BlinkMacSystemFont, -apple-system, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
|
} */
|
||||||
|
|
||||||
|
a,a:hover {
|
||||||
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes App-logo-spin {
|
@keyframes App-logo-spin {
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import 'bulma/css/bulma.css';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
import AppRoute from './RouteMenu';
|
import RouteMenu from './RouteMenu';
|
||||||
|
|
||||||
class App extends React.Component {
|
class App extends React.Component {
|
||||||
public render() {
|
public render() {
|
||||||
return (
|
return (
|
||||||
<div className="App">
|
<div className="App">
|
||||||
<AppRoute />
|
<RouteMenu />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import {
|
|||||||
} from 'recharts';
|
} from 'recharts';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import { Container, Title } from 'bloomer';
|
import { Card, CardImage, CardHeader, CardHeaderTitle } from 'bloomer';
|
||||||
// const randomColor = require('randomcolor');
|
const randomColor = require('randomcolor');
|
||||||
import * as Papa from 'papaparse';
|
import * as Papa from 'papaparse';
|
||||||
|
|
||||||
|
|
||||||
@@ -49,23 +49,32 @@ export class Chart extends React.Component<any, any> {
|
|||||||
// );
|
// );
|
||||||
// };
|
// };
|
||||||
const colorMap = this.props.colorMap;
|
const colorMap = this.props.colorMap;
|
||||||
|
// const LabeText = (props: any) => {
|
||||||
|
// return (<text>{props.name}</text>);
|
||||||
|
// };
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Card>
|
||||||
<Title isSize={4}>Plotting {_.capitalize(this.props.chartColumn)}</Title>
|
<CardHeader>
|
||||||
<ResponsiveContainer width="100%" height={200}>
|
<CardHeaderTitle className='is-centered'>
|
||||||
<PieChart>
|
{this.props.title}
|
||||||
<Pie data={chartData} dataKey='value' outerRadius={100} label={true} labelLine={false}>
|
</CardHeaderTitle>
|
||||||
{
|
</CardHeader>
|
||||||
chartData.map((_0, _1) => {
|
<CardImage>
|
||||||
const color = _.get(colorMap, _0.name, 'gray');
|
<ResponsiveContainer width="100%" height={300}>
|
||||||
return (<Cell key={_1} fill={color} />)
|
<PieChart>
|
||||||
})
|
<Pie data={chartData} dataKey='value' outerRadius={100} labelLine={true} label={true}>
|
||||||
}
|
{
|
||||||
</Pie>
|
chartData.map((_0, _1) => {
|
||||||
<Tooltip />
|
const color = _.get(colorMap, _0.name, randomColor());
|
||||||
</PieChart>
|
return (<Cell key={_1} fill={color} />)
|
||||||
</ResponsiveContainer>
|
})
|
||||||
</Container>
|
}
|
||||||
|
</Pie>
|
||||||
|
<Tooltip />
|
||||||
|
</PieChart>
|
||||||
|
</ResponsiveContainer>
|
||||||
|
</CardImage>
|
||||||
|
</Card>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,17 +6,20 @@ export default class ChartLoader extends React.Component<any, any> {
|
|||||||
public render() {
|
public render() {
|
||||||
const colorMaps = this.props.colorMaps;
|
const colorMaps = this.props.colorMaps;
|
||||||
return (
|
return (
|
||||||
<Columns>
|
<Columns isCentered={true} isMultiline={true} style={{
|
||||||
|
backgroundColor:'#f0f0f0'
|
||||||
|
}}>
|
||||||
{this.props.chartList.map((o: any, i: number) => {
|
{this.props.chartList.map((o: any, i: number) => {
|
||||||
const colorMap = colorMaps[o.chartColumn];
|
const colorMap = colorMaps[o.chartColumn];
|
||||||
return (
|
return (
|
||||||
<Column key={i} isSize={3}>
|
<Column key={i} isSize={4}>
|
||||||
<Chart csvFile={o.fileName} chartColumn={o.chartColumn} colorMap={colorMap} />
|
<Chart
|
||||||
|
csvFile={o.fileName} chartColumn={o.chartColumn}
|
||||||
|
colorMap={colorMap} title={o.chartTitle ? o.chartTitle: o.chartColumn}
|
||||||
|
/>
|
||||||
</Column>
|
</Column>
|
||||||
);
|
);
|
||||||
}
|
})}
|
||||||
|
|
||||||
)}
|
|
||||||
</Columns>
|
</Columns>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
2
src/Config.tsx
Normal file
2
src/Config.tsx
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export const apiHost = process.env.REACT_APP_API_HOST
|
||||||
|
export const apiDir = process.env.REACT_APP_API_DIR
|
||||||
@@ -6,25 +6,25 @@ import {
|
|||||||
} 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 * as local from 'localforage';
|
||||||
import 'bulma/css/bulma.css';
|
|
||||||
import ServerTabLoader from './ServerTabLoader';
|
import ServerTabLoader from './ServerTabLoader';
|
||||||
import ChartLoader from './ChartLoader';
|
import ChartLoader from './ChartLoader';
|
||||||
|
import { apiDir } from './Config';
|
||||||
|
|
||||||
const navButton = (name: string, link: string) => (
|
const navButton = (name: string, link: string) => (
|
||||||
<Link to={link}>{name}</Link>
|
<Link to={link}>{name}</Link>
|
||||||
);
|
);
|
||||||
|
|
||||||
const RedirectCharts = () => (<Redirect to='/charts' />);
|
const RedirectCharts = () => (<Redirect to={apiDir+'charts'} />);
|
||||||
|
|
||||||
class AppRoute extends React.Component {
|
class RouteMenu extends React.Component {
|
||||||
constructor(props: any) {
|
constructor(props: any) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
tabList:[],
|
tabList: [],
|
||||||
chartList: [],
|
chartList: [],
|
||||||
colorMaps:{}
|
colorMaps: {}
|
||||||
}
|
}
|
||||||
fetch('/config.json')
|
fetch(apiDir+'config.json')
|
||||||
.then((response) => response.text())
|
.then((response) => response.text())
|
||||||
.then((jsonStr) => {
|
.then((jsonStr) => {
|
||||||
const jsonObj = JSON.parse(jsonStr);
|
const jsonObj = JSON.parse(jsonStr);
|
||||||
@@ -39,27 +39,27 @@ class AppRoute extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const ConfiguredChart = () => (<ChartLoader {...this.state}/>);
|
const ConfiguredChart = () => (<ChartLoader {...this.state} />);
|
||||||
const ConfiguredServerTab = () => (<ServerTabLoader {...this.state}/>);
|
const ConfiguredServerTab = () => (<ServerTabLoader {...this.state} />);
|
||||||
return (
|
return (
|
||||||
<Router>
|
<Router>
|
||||||
<div>
|
<div>
|
||||||
<Container isFluid={true} isMarginless={true} isFullWidth={true}>
|
<Container isFluid={true} isMarginless={true} isFullWidth={true}>
|
||||||
<Navbar style={{ border: 'solid 1px #00D1B2', margin: '0' }}>
|
<Navbar style={{ backgroundColor: '#00D1B2' }}>
|
||||||
<NavbarMenu isActive={true}>
|
<NavbarMenu isActive={true}>
|
||||||
<NavbarItem >{navButton('Charts', '/charts')}</NavbarItem>
|
<NavbarItem >{navButton('Charts', apiDir + 'charts')}</NavbarItem>
|
||||||
<NavbarItem>{navButton('Tables', '/tables')}</NavbarItem>
|
<NavbarItem>{navButton('Tables', apiDir + 'tables')}</NavbarItem>
|
||||||
</NavbarMenu>
|
</NavbarMenu>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
</Container>
|
</Container>
|
||||||
<Section isPaddingless={true}>
|
<Section isPaddingless={true}>
|
||||||
<Route exact={true} path="/" component={RedirectCharts} />
|
<Route exact={true} path={apiDir} component={RedirectCharts} />
|
||||||
<Route path="/charts" component={ConfiguredChart} />
|
<Route path={apiDir + "charts"} component={ConfiguredChart} />
|
||||||
<Route path="/tables" component={ConfiguredServerTab} />
|
<Route path={apiDir + "tables"} component={ConfiguredServerTab} />
|
||||||
</Section>
|
</Section>
|
||||||
</div>
|
</div>
|
||||||
</Router>
|
</Router>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export default AppRoute
|
export default RouteMenu
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ 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');
|
||||||
|
import { apiDir } from './Config';
|
||||||
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';
|
||||||
@@ -27,7 +28,7 @@ export default class ServerTable extends React.Component<any, any> {
|
|||||||
colColorMap
|
colColorMap
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Papa.parse(this.props.csvFile, {
|
Papa.parse(apiDir + this.props.csvFile, {
|
||||||
header: true,
|
header: true,
|
||||||
download: true,
|
download: true,
|
||||||
skipEmptyLines: true,
|
skipEmptyLines: true,
|
||||||
@@ -40,8 +41,8 @@ export default class ServerTable extends React.Component<any, any> {
|
|||||||
const data = this.state.data;
|
const data = this.state.data;
|
||||||
const headers = this.state.headers;
|
const headers = this.state.headers;
|
||||||
const filterPart = (filter: any, row: any) =>
|
const filterPart = (filter: any, row: any) =>
|
||||||
String(row[filter.id]).startsWith(filter.value) ||
|
String(_.toLower(row[filter.id])).startsWith(_.toLower(filter.value)) ||
|
||||||
String(row[filter.id]).endsWith(filter.value)
|
String(_.toLower(row[filter.id])).endsWith(_.toLower(filter.value))
|
||||||
const headerGen = (headerName: string) => {
|
const headerGen = (headerName: string) => {
|
||||||
// const title = headerName
|
// const title = headerName
|
||||||
// .replace(/([A-Z])/g, ' $1')
|
// .replace(/([A-Z])/g, ' $1')
|
||||||
@@ -68,6 +69,11 @@ export default class ServerTable extends React.Component<any, any> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
const colStyle = () => ({
|
||||||
|
style: {
|
||||||
|
textAlign: 'left'
|
||||||
|
}
|
||||||
|
});
|
||||||
const headerCols = headers.map(headerGen);
|
const headerCols = headers.map(headerGen);
|
||||||
return (
|
return (
|
||||||
<ReactTable
|
<ReactTable
|
||||||
@@ -79,6 +85,7 @@ export default class ServerTable extends React.Component<any, any> {
|
|||||||
defaultPageSize={100}
|
defaultPageSize={100}
|
||||||
className="-striped -highlight"
|
className="-striped -highlight"
|
||||||
getTrProps={rowStyle}
|
getTrProps={rowStyle}
|
||||||
|
getTdProps={colStyle}
|
||||||
style={{
|
style={{
|
||||||
height: "75vh"
|
height: "75vh"
|
||||||
}}
|
}}
|
||||||
@@ -88,7 +95,6 @@ export default class ServerTable extends React.Component<any, any> {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{makeTable()}
|
{makeTable()}
|
||||||
{/* <Chart data={lastFiltered} /> */}
|
|
||||||
<Button>
|
<Button>
|
||||||
<CSVLink data={lastFiltered} filename={"data.csv"}>
|
<CSVLink data={lastFiltered} filename={"data.csv"}>
|
||||||
Download CSV
|
Download CSV
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ import * as React from 'react';
|
|||||||
import * as ReactDOM from 'react-dom';
|
import * as ReactDOM from 'react-dom';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
import registerServiceWorker from './registerServiceWorker';
|
// import registerServiceWorker from './registerServiceWorker';
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<App />,
|
<App />,
|
||||||
document.getElementById('root') as HTMLElement
|
document.getElementById('root') as HTMLElement
|
||||||
);
|
);
|
||||||
registerServiceWorker();
|
// registerServiceWorker();
|
||||||
|
|||||||
Reference in New Issue
Block a user