Compare commits

...

18 Commits

Author SHA1 Message Date
ef3b9935a8 Update '.gitignore' 2018-08-04 21:13:14 +00:00
502121b536 Apache htaccess redirection 2018-08-04 21:12:20 +00:00
4039a74fd7 Update '.env' 2018-08-04 21:11:01 +00:00
Malar Kannan
b3358023f1 static serving under path 2018-08-03 21:57:25 +05:30
Malar Kannan
dc9c0d5e59 added configurable root directory in .env* files 2018-08-03 00:11:20 +05:30
Malar Kannan
6bdb8b6174 menu aesthetics 2018-07-02 00:43:06 +05:30
Malar Kannan
97e628c4e1 added plot titles to config 2018-07-02 00:06:04 +05:30
Malar Kannan
b02c090d03 add multiple lines if number of charts are more 2018-07-02 00:01:28 +05:30
Malar Kannan
2dcb19c8ee added card for charts with borders 2018-07-01 22:57:37 +05:30
Malar Kannan
2aae9ee455 centered charts 2018-07-01 22:50:23 +05:30
Malar Kannan
0dcad337ed 1. fixed hover issue
2. search is case insensitive on tables
3. text aligned left
2018-07-01 22:46:47 +05:30
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
Malar Kannan
311180189f removed line from chart 2018-07-01 21:12:54 +05:30
Malar Kannan
e1c6e4923c added static labels on chart 2018-07-01 21:01:27 +05:30
Malar Kannan
8694d0d86c added pie chart for single column 2018-07-01 19:42:00 +05:30
Malar Kannan
6492047c7c added local forage support for config saving 2018-06-30 19:32:38 +05:30
Malar Kannan
cb0c3966e1 random color for row with same value in the column in config 2018-06-30 15:04:49 +05:30
16 changed files with 425 additions and 72 deletions

3
.env Normal file
View 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
View File

@@ -0,0 +1,2 @@
REACT_APP_API_HOST="http://localhost:3000/"
REACT_APP_API_DIR="/"

1
.gitignore vendored
View File

@@ -66,6 +66,7 @@ build/Release
# Dependency directories
node_modules/
jspm_packages/
build/
# Typescript v1 declaration files
typings/

View File

@@ -3,12 +3,17 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"bloomer": "^0.6.3",
"bulma": "^0.7.1",
"localforage": "^1.7.2",
"lodash": "^4.17.10",
"namor": "^1.0.1",
"papaparse": "^4.5.0",
"randomcolor": "^0.5.3",
"react": "^16.4.1",
"react-csv": "^1.0.14",
"react-dom": "^16.4.1",
"react-router-dom": "^4.3.1",
"react-scripts-ts": "2.16.0",
"react-table": "^6.8.6",
"react-tabs": "^2.2.2",
@@ -22,11 +27,14 @@
},
"devDependencies": {
"@types/jest": "^23.1.1",
"@types/localforage": "^0.0.34",
"@types/lodash": "^4.14.110",
"@types/node": "^10.3.4",
"@types/papaparse": "^4.5.0",
"@types/randomcolor": "^0.4.3",
"@types/react": "^16.4.1",
"@types/react-dom": "^16.0.6",
"@types/react-router-dom": "^4.2.7",
"@types/react-table": "^6.7.11",
"@types/react-tabs": "^1.0.4",
"@types/recharts": "^1.0.23",

4
public/.htaccess Normal file
View File

@@ -0,0 +1,4 @@
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]

View File

@@ -1,7 +1,8 @@
{
"tabList": [{
"tabTitle": "Tab 1",
"fileName": "data.csv"
"fileName": "data.csv",
"colorColumn": "status"
},
{
"tabTitle": "Tab 2",
@@ -16,8 +17,35 @@
"fileName": "data.csv"
},
{
"tabTitle": "Tab 4",
"tabTitle": "Tab 6",
"fileName": "data.csv"
}
]
],
"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",
"chartColumn": "status"
}
],
"colorMaps": {
"status": {
"complicated": "red",
"single": "green"
}
}
}

View File

@@ -22,7 +22,24 @@
font-size: large;
}
@keyframes App-logo-spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
.navbar-item:hover {
background-color: rgba(10, 10, 10, .1);
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 {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

View File

@@ -1,12 +1,13 @@
import * as React from 'react';
import 'bulma/css/bulma.css';
import './App.css';
import ServerTabLoader from './ServerTabLoader';
import RouteMenu from './RouteMenu';
class App extends React.Component {
public render() {
return (
<div className="App">
<ServerTabLoader/>
<RouteMenu />
</div>
);
}

View File

@@ -1,22 +1,80 @@
import {
PieChart, Pie, ResponsiveContainer, Tooltip
PieChart, Pie, ResponsiveContainer, Tooltip, Cell
} from 'recharts';
import * as React from 'react';
import * as _ from 'lodash';
import { Card, CardImage, CardHeader, CardHeaderTitle } from 'bloomer';
const randomColor = require('randomcolor');
import * as Papa from 'papaparse';
export class Chart extends React.Component<any, any> {
constructor(props: any) {
super(props);
this.state = { data: [] };
const loaded = (results: any) => {
const local = this;
local.setState({
headers: results.meta.fields,
data: results.data,
});
}
Papa.parse(this.props.csvFile, {
header: true,
download: true,
skipEmptyLines: true,
dynamicTyping: true,
complete: loaded
});
}
public render() {
const data = this.props.data;
const data = this.state.data;
const countMap = _.countBy(data, (o: any) => _.get<any>(o, this.props.chartColumn))
const chartData = _.map(_.keys(countMap), (k: any) => {
return {
name: k,
value: countMap[k],
}
})
// const RADIAN = Math.PI / 180;
// const renderCustomizedLabel = ({ cx, cy, midAngle, innerRadius, outerRadius, percent, index }:any) => {
// const radius = innerRadius + (outerRadius - innerRadius) * 0.5;
// const x = cx + radius * Math.cos(-midAngle * RADIAN);
// const y = cy + radius * Math.sin(-midAngle * RADIAN);
//
// return (
// <text x={x} y={y} fill="white" textAnchor='middle' dominantBaseline="central">
// {chartData[index].name}
// </text>
// );
// };
const colorMap = this.props.colorMap;
// const LabeText = (props: any) => {
// return (<text>{props.name}</text>);
// };
return (
<ResponsiveContainer width="100%" height={200}>
<PieChart>
<Pie data={data} dataKey="age" cx={600} cy={100} outerRadius={80} fill="#82ca9d" />
<Tooltip />
</PieChart>
</ResponsiveContainer>
<Card>
<CardHeader>
<CardHeaderTitle className='is-centered'>
{this.props.title}
</CardHeaderTitle>
</CardHeader>
<CardImage>
<ResponsiveContainer width="100%" height={300}>
<PieChart>
<Pie data={chartData} dataKey='value' outerRadius={100} labelLine={true} label={true}>
{
chartData.map((_0, _1) => {
const color = _.get(colorMap, _0.name, randomColor());
return (<Cell key={_1} fill={color} />)
})
}
</Pie>
<Tooltip />
</PieChart>
</ResponsiveContainer>
</CardImage>
</Card>
)
}
}

26
src/ChartLoader.tsx Normal file
View File

@@ -0,0 +1,26 @@
import * as React from 'react';
import { Columns, Column } from 'bloomer';
import { Chart } from './Chart';
export default class ChartLoader extends React.Component<any, any> {
public render() {
const colorMaps = this.props.colorMaps;
return (
<Columns isCentered={true} isMultiline={true} style={{
backgroundColor:'#f0f0f0'
}}>
{this.props.chartList.map((o: any, i: number) => {
const colorMap = colorMaps[o.chartColumn];
return (
<Column key={i} isSize={4}>
<Chart
csvFile={o.fileName} chartColumn={o.chartColumn}
colorMap={colorMap} title={o.chartTitle ? o.chartTitle: o.chartColumn}
/>
</Column>
);
})}
</Columns>
)
}
}

2
src/Config.tsx Normal file
View File

@@ -0,0 +1,2 @@
export const apiHost = process.env.REACT_APP_API_HOST
export const apiDir = process.env.REACT_APP_API_DIR

65
src/RouteMenu.tsx Normal file
View File

@@ -0,0 +1,65 @@
import * as React from 'react';
import {
BrowserRouter as Router,
Route, Redirect,
Link
} from 'react-router-dom';
import { Container, Navbar, NavbarItem, NavbarMenu, Section } from 'bloomer';
import * as local from 'localforage';
import ServerTabLoader from './ServerTabLoader';
import ChartLoader from './ChartLoader';
import { apiDir } from './Config';
const navButton = (name: string, link: string) => (
<Link to={link}>{name}</Link>
);
const RedirectCharts = () => (<Redirect to={apiDir+'charts'} />);
class RouteMenu extends React.Component {
constructor(props: any) {
super(props);
this.state = {
tabList: [],
chartList: [],
colorMaps: {}
}
fetch(apiDir+'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>
<div>
<Container isFluid={true} isMarginless={true} isFullWidth={true}>
<Navbar style={{ backgroundColor: '#00D1B2' }}>
<NavbarMenu isActive={true}>
<NavbarItem >{navButton('Charts', apiDir + 'charts')}</NavbarItem>
<NavbarItem>{navButton('Tables', apiDir + 'tables')}</NavbarItem>
</NavbarMenu>
</Navbar>
</Container>
<Section isPaddingless={true}>
<Route exact={true} path={apiDir} component={RedirectCharts} />
<Route path={apiDir + "charts"} component={ConfiguredChart} />
<Route path={apiDir + "tables"} component={ConfiguredServerTab} />
</Section>
</div>
</Router>
);
}
}
export default RouteMenu

View File

@@ -1,43 +1,34 @@
import * as React from 'react';
import * as _ from 'lodash';
import ServerTable from './ServerTable';
import { Tabs, TabList, TabPanel, Tab } from 'react-tabs';
import { Hero, HeroBody } from 'bloomer';
import './Tabs.css';
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 });
})
.catch((e) => {
this.setState({ message: e.stack, showMessage: true });
});
}
public render() {
return (
<Tabs forceRenderTabPanel={true}>
<TabList>
{this.state.tabList.map((o: any, i: number) =>
(<Tab key={i}>{o.tabTitle}</Tab>)
)}
</TabList>
{this.state.tabList.map((o: any, i: number) =>
(<TabPanel key={i}>
<ServerTable csvFile={o.fileName} />
</TabPanel>
)
)}
</Tabs>
<Hero isColor='light' isSize='large' isFullWidth={true} isFullHeight={true}>
<HeroBody isPaddingless={true} isDisplay='block'>
<Tabs forceRenderTabPanel={true}>
<TabList>
{this.props.tabList.map((o: any, i: number) =>
(<Tab key={i}>{o.tabTitle}</Tab>)
)}
</TabList>
{this.props.tabList.map((o: any, i: number) => {
const colorMap = this.props.colorMaps[o.colorColumn];
return (
<TabPanel key={i}>
<ServerTable csvFile={o.fileName} colorColumn={o.colorColumn} colorMap={colorMap} />
</TabPanel>
);
}
)}
</Tabs>
</HeroBody>
</Hero>
)
}
}

View File

@@ -1,7 +1,9 @@
import * as React from 'react';
import { Tips } from "./Utils";
import * as _ from 'lodash';
// import { Chart } from './Chart';
import { Button } from 'bloomer';
// const randomColor = require('randomcolor');
import { apiDir } from './Config';
const reactcsv = require('react-csv');
const CSVLink = reactcsv.CSVLink;
import * as Papa from 'papaparse';
@@ -14,16 +16,19 @@ export default class ServerTable extends React.Component<any, any> {
constructor(props: any) {
super(props);
this.state = {
headers: [], data: []
headers: [], data: [], colColorMap: {}
}
const loaded = (results: any) => {
const localstate = this;
localstate.setState({
const local = this;
// const colsUnique = _.keys(_.groupBy(results.data, (o: any) => _.get<any>(o, this.props.colorColumn)));
const colColorMap = this.props.colorMap; // _.zipObject(colsUnique, _.map(colsUnique, () => randomColor()));
local.setState({
headers: results.meta.fields,
data: results.data
data: results.data,
colColorMap
});
}
Papa.parse(this.props.csvFile, {
Papa.parse(apiDir + this.props.csvFile, {
header: true,
download: true,
skipEmptyLines: true,
@@ -36,17 +41,39 @@ export default class ServerTable extends React.Component<any, any> {
const data = this.state.data;
const headers = this.state.headers;
const filterPart = (filter: any, row: any) =>
String(row[filter.id]).startsWith(filter.value) ||
String(row[filter.id]).endsWith(filter.value)
String(_.toLower(row[filter.id])).startsWith(_.toLower(filter.value)) ||
String(_.toLower(row[filter.id])).endsWith(_.toLower(filter.value))
const headerGen = (headerName: string) => {
const title = headerName
.replace(/([A-Z])/g, ' $1')
.replace(/^./, (str: string) => str.toUpperCase());
// const title = headerName
// .replace(/([A-Z])/g, ' $1')
// .replace(/^./, (str: string) => str.toUpperCase());
return {
Header: title,
accessor: headerName
Header: headerName,
accessor: headerName,
Cell: (row: any) => {
return row.value;
}
}
}
const colorCol = this.props.colorColumn;
const colColorMap = this.state.colColorMap;
const rowStyle = (_0: any, rowInfo: any, _1: any) => {
if (_.isUndefined(rowInfo) || _.isUndefined(colorCol)) {
return {};
}
const colValue = _.get<any>(rowInfo.row, colorCol, '');
const colColor = _.get<any>(colColorMap, colValue, 'white');
return {
style: {
background: colColor
}
};
};
const colStyle = () => ({
style: {
textAlign: 'left'
}
});
const headerCols = headers.map(headerGen);
return (
<ReactTable
@@ -57,8 +84,10 @@ export default class ServerTable extends React.Component<any, any> {
showPagination={false}
defaultPageSize={100}
className="-striped -highlight"
getTrProps={rowStyle}
getTdProps={colStyle}
style={{
height: "500px"
height: "75vh"
}}
>
{(state, makeTable, ) => {
@@ -66,10 +95,11 @@ export default class ServerTable extends React.Component<any, any> {
return (
<div>
{makeTable()}
{/* <Chart data={lastFiltered} /> */}
<CSVLink data={lastFiltered} filename={"data.csv"}>
Download CSV
</CSVLink>
<Button>
<CSVLink data={lastFiltered} filename={"data.csv"}>
Download CSV
</CSVLink>
</Button>
<br />
<Tips />
</div>

View File

@@ -2,10 +2,10 @@ import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';
import './index.css';
import registerServiceWorker from './registerServiceWorker';
// import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(
<App />,
document.getElementById('root') as HTMLElement
);
registerServiceWorker();
// registerServiceWorker();

125
yarn.lock
View File

@@ -26,10 +26,20 @@
dependencies:
"@types/d3-path" "*"
"@types/history@*":
version "4.6.2"
resolved "https://registry.yarnpkg.com/@types/history/-/history-4.6.2.tgz#12cfaba693ba20f114ed5765467ff25fdf67ddb0"
"@types/jest@^23.1.1":
version "23.1.1"
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-23.1.1.tgz#c54ab1a5f41aa693c0957222dd10414416d0c87b"
"@types/localforage@^0.0.34":
version "0.0.34"
resolved "https://registry.yarnpkg.com/@types/localforage/-/localforage-0.0.34.tgz#5e31c32dd8791ec4b9ff3ef47c9cb55b2d0d9438"
dependencies:
localforage "*"
"@types/lodash@^4.14.110":
version "4.14.110"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.110.tgz#fb07498f84152947f30ea09d89207ca07123461e"
@@ -42,6 +52,10 @@
version "4.5.0"
resolved "https://registry.yarnpkg.com/@types/papaparse/-/papaparse-4.5.0.tgz#6a3f1ff2d70fa96945617a12edc4b0490a18ec14"
"@types/randomcolor@^0.4.3":
version "0.4.3"
resolved "https://registry.yarnpkg.com/@types/randomcolor/-/randomcolor-0.4.3.tgz#66bf69fdf43ea7b73ae4c378f660442c8e236e93"
"@types/react-dom@^16.0.6":
version "16.0.6"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.0.6.tgz#f1a65a4e7be8ed5d123f8b3b9eacc913e35a1a3c"
@@ -49,6 +63,21 @@
"@types/node" "*"
"@types/react" "*"
"@types/react-router-dom@^4.2.7":
version "4.2.7"
resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-4.2.7.tgz#9d36bfe175f916dd8d7b6b0237feed6cce376b4c"
dependencies:
"@types/history" "*"
"@types/react" "*"
"@types/react-router" "*"
"@types/react-router@*":
version "4.0.27"
resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-4.0.27.tgz#553f54df7c4b09d6046b0201ce9b91c46b2940e3"
dependencies:
"@types/history" "*"
"@types/react" "*"
"@types/react-table@^6.7.11":
version "6.7.11"
resolved "https://registry.yarnpkg.com/@types/react-table/-/react-table-6.7.11.tgz#26e85411981054af7dd657ef81e249baa6aee3d5"
@@ -1058,6 +1087,13 @@ binary-extensions@^1.0.0:
version "1.11.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205"
bloomer@^0.6.3:
version "0.6.3"
resolved "https://registry.yarnpkg.com/bloomer/-/bloomer-0.6.3.tgz#4899cebb1992e934a148df942fbc37ce298e7669"
dependencies:
classnames "^2.2.5"
tslib "^1.7.0"
bluebird@^3.4.7, bluebird@^3.5.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9"
@@ -1252,6 +1288,10 @@ builtin-status-codes@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
bulma@^0.7.1:
version "0.7.1"
resolved "https://registry.yarnpkg.com/bulma/-/bulma-0.7.1.tgz#73c2e3b2930c90cc272029cbd19918b493fca486"
bytes@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
@@ -3161,6 +3201,16 @@ he@1.1.x:
version "1.1.1"
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
history@^4.7.2:
version "4.7.2"
resolved "https://registry.yarnpkg.com/history/-/history-4.7.2.tgz#22b5c7f31633c5b8021c7f4a8a954ac139ee8d5b"
dependencies:
invariant "^2.2.1"
loose-envify "^1.2.0"
resolve-pathname "^2.2.0"
value-equal "^0.4.0"
warning "^3.0.0"
hmac-drbg@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
@@ -3169,6 +3219,10 @@ hmac-drbg@^1.0.0:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
hoist-non-react-statics@^2.5.0:
version "2.5.5"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47"
home-or-tmp@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8"
@@ -3330,6 +3384,10 @@ ignore-walk@^3.0.1:
dependencies:
minimatch "^3.0.4"
immediate@~3.0.5:
version "3.0.6"
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
import-lazy@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
@@ -3414,7 +3472,7 @@ interpret@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614"
invariant@^2.2.2:
invariant@^2.2.1, invariant@^2.2.2, invariant@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
dependencies:
@@ -4260,6 +4318,12 @@ levn@~0.3.0:
prelude-ls "~1.1.2"
type-check "~0.3.2"
lie@3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e"
dependencies:
immediate "~3.0.5"
load-json-file@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
@@ -4300,6 +4364,12 @@ loader-utils@^1.0.2, loader-utils@^1.1.0:
emojis-list "^2.0.0"
json5 "^0.5.0"
localforage@*, localforage@^1.7.2:
version "1.7.2"
resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.7.2.tgz#fa4442602f806edd2bca6a54ab4e656f031f121c"
dependencies:
lie "3.1.1"
locate-path@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
@@ -4376,7 +4446,7 @@ longest@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1:
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
dependencies:
@@ -5143,7 +5213,7 @@ path-to-regexp@0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
path-to-regexp@^1.0.1:
path-to-regexp@^1.0.1, path-to-regexp@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d"
dependencies:
@@ -5672,6 +5742,10 @@ randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5:
dependencies:
safe-buffer "^5.1.0"
randomcolor@^0.5.3:
version "0.5.3"
resolved "https://registry.yarnpkg.com/randomcolor/-/randomcolor-0.5.3.tgz#7f90f2f2a7f6d5a52232161eeaeeaea9ac3b5815"
randomfill@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458"
@@ -5747,6 +5821,29 @@ react-resize-detector@1.1.0:
dependencies:
prop-types "^15.5.10"
react-router-dom@^4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.3.1.tgz#4c2619fc24c4fa87c9fd18f4fb4a43fe63fbd5c6"
dependencies:
history "^4.7.2"
invariant "^2.2.4"
loose-envify "^1.3.1"
prop-types "^15.6.1"
react-router "^4.3.1"
warning "^4.0.1"
react-router@^4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.3.1.tgz#aada4aef14c809cb2e686b05cee4742234506c4e"
dependencies:
history "^4.7.2"
hoist-non-react-statics "^2.5.0"
invariant "^2.2.4"
loose-envify "^1.3.1"
path-to-regexp "^1.7.0"
prop-types "^15.6.1"
warning "^4.0.1"
react-scripts-ts@2.16.0:
version "2.16.0"
resolved "https://registry.yarnpkg.com/react-scripts-ts/-/react-scripts-ts-2.16.0.tgz#45f831a12139c3b59d6bb729c1b6ef51e0f22908"
@@ -6115,6 +6212,10 @@ resolve-from@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748"
resolve-pathname@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-2.2.0.tgz#7e9ae21ed815fd63ab189adeee64dc831eefa879"
resolve-url@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
@@ -6948,7 +7049,7 @@ tsconfig-paths@^3.1.1:
strip-bom "^3.0.0"
strip-json-comments "^2.0.1"
tslib@^1.8.0, tslib@^1.8.1:
tslib@^1.7.0, tslib@^1.8.0, tslib@^1.8.1:
version "1.9.3"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
@@ -7254,6 +7355,10 @@ validate-npm-package-license@^3.0.1:
spdx-correct "^3.0.0"
spdx-expression-parse "^3.0.0"
value-equal@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-0.4.0.tgz#c5bdd2f54ee093c04839d71ce2e4758a6890abc7"
vary@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
@@ -7288,6 +7393,18 @@ walker@~1.0.5:
dependencies:
makeerror "1.0.x"
warning@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c"
dependencies:
loose-envify "^1.0.0"
warning@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.1.tgz#66ce376b7fbfe8a887c22bdf0e7349d73d397745"
dependencies:
loose-envify "^1.0.0"
watch@~0.18.0:
version "0.18.0"
resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986"