diff --git a/.env.development b/.env.development
index 7d9285bc..13223e44 100644
--- a/.env.development
+++ b/.env.development
@@ -1 +1 @@
-REACT_APP_BASE_URL='http://testnet.solana.com'
+REACT_APP_BASE_URL='edge.testnet.solana.com'
diff --git a/.eslintrc.js b/.eslintrc.js
index 6ac3c066..4bbbf588 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -8,8 +8,9 @@ module.exports = {
es6: true,
node: true,
},
- plugins: ['react'],
+ plugins: ['react', 'flowtype'],
extends: [
+ 'plugin:flowtype/recommended',
'eslint:recommended',
'plugin:react/recommended',
'plugin:import/errors',
diff --git a/config-overrides.js b/config-overrides.js
index 5b3719b9..0048c848 100644
--- a/config-overrides.js
+++ b/config-overrides.js
@@ -3,5 +3,6 @@ const {override, addBabelPlugin} = require('customize-cra');
module.exports = override(
// addBabelPlugin('lodash'),
+ addBabelPlugin('date-fns'),
addBabelPlugin('react-hot-loader/babel'),
);
diff --git a/package.json b/package.json
index fb75398e..08e20779 100644
--- a/package.json
+++ b/package.json
@@ -12,12 +12,14 @@
"url": "http://github.com/solana-labs/blockexplorer/issues"
},
"dependencies": {
+ "@nivo/line": "^0.59.1",
"@solana/web3.js": "^0.16.10",
"babel-plugin-transform-runtime": "^6.23.0",
"base-58": "^0.0.1",
"classnames": "^2.2.6",
"copy-to-clipboard": "^3.2.0",
"cors": "^2.8.5",
+ "date-fns": "^1.30.1",
"express": "^4.17.1",
"express-ws": "^4.0.0",
"geoip-lite": "^1.3.7",
@@ -36,8 +38,6 @@
"yaml": "^1.6.0"
},
"devDependencies": {
- "@babel/plugin-proposal-class-properties": "^7.5.0",
- "@babel/plugin-proposal-decorators": "^7.4.4",
"@babel/register": "^7.4.4",
"@commitlint/config-conventional": "^8.0.0",
"@commitlint/travis-cli": "^8.0.0",
@@ -46,6 +46,7 @@
"axios": "^0.19.0",
"babel-cli": "^6.26.0",
"babel-eslint": "^10.0.2",
+ "babel-plugin-date-fns": "^0.2.1",
"babel-plugin-lodash": "^3.3.4",
"babel-preset-env": "^1.7.0",
"chart.js": "^2.8.0",
diff --git a/src/AppV2.js b/src/AppV2.js
index 290e5132..6c00bb63 100644
--- a/src/AppV2.js
+++ b/src/AppV2.js
@@ -5,19 +5,23 @@ import {hot} from 'react-hot-loader/root';
import {Route, Switch} from 'react-router-dom';
import Header from 'v2/components/Header';
import NavBar from 'v2/components/NavBar';
+import Footer from 'v2/components/Footer';
import theme from 'v2/theme';
+import socket from 'v2/stores/socket';
+
+socket.init();
const Dashboard = lazy(() => import('v2/components/Dashboard'));
const useStyles = makeStyles(theme => ({
root: {
display: 'flex',
+ overflow: 'hidden',
},
content: {
flexGrow: 1,
marginLeft: 50,
- padding: theme.spacing(3),
- paddingTop: 50,
+ padding: '50px 24px 0 24px',
},
toolbar: {
display: 'flex',
@@ -40,9 +44,10 @@ const App = () => {
Loading...}>
-
+
+
diff --git a/src/index.js b/src/index.js
index f1955389..7fa9335e 100755
--- a/src/index.js
+++ b/src/index.js
@@ -4,12 +4,12 @@ import {BrowserRouter} from 'react-router-dom';
import './index.css';
import App from './App';
-// import AppV2 from './AppV2';
+import AppV2 from './AppV2';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(
- {window.location.pathname.includes('v2') ? : }
+ {window.location.pathname.includes('rc') ? : }
,
document.getElementById('root'),
);
diff --git a/src/v2/api/socket.js b/src/v2/api/socket.js
new file mode 100644
index 00000000..6b912dc5
--- /dev/null
+++ b/src/v2/api/socket.js
@@ -0,0 +1,6 @@
+import RobustWebSocket from 'robust-websocket';
+import {BLOCK_EXPLORER_WS_API_BASE} from 'v2/const';
+
+export const initSocket = () => {
+ return new RobustWebSocket(BLOCK_EXPLORER_WS_API_BASE);
+};
diff --git a/src/v2/api/stats.js b/src/v2/api/stats.js
index 4f72e8c5..4616531c 100644
--- a/src/v2/api/stats.js
+++ b/src/v2/api/stats.js
@@ -3,3 +3,7 @@ import api from '.';
export function getStats() {
return api('/global-stats');
}
+
+export function getTxnStats() {
+ return api('/txn-stats');
+}
diff --git a/src/v2/assets/icons/arrow-right.png b/src/v2/assets/icons/arrow-right.png
new file mode 100644
index 00000000..0c16d1b6
Binary files /dev/null and b/src/v2/assets/icons/arrow-right.png differ
diff --git a/src/v2/components/Dashboard/NetworkOverview/NodesMap/index.jsx b/src/v2/components/Dashboard/NetworkOverview/NodesMap/index.jsx
new file mode 100644
index 00000000..b2404458
--- /dev/null
+++ b/src/v2/components/Dashboard/NetworkOverview/NodesMap/index.jsx
@@ -0,0 +1,98 @@
+import {Typography} from '@material-ui/core';
+import {observer} from 'mobx-react-lite';
+import React from 'react';
+import {
+ ComposableMap,
+ Geographies,
+ Geography,
+ Marker,
+ Markers,
+ ZoomableGroup,
+} from 'react-simple-maps';
+import {map} from 'lodash/fp';
+import NodesStore from 'v2/stores/nodes';
+import MapTooltip from 'v2/components/UI/MapTooltip';
+import {mapStyle, markerStyle} from 'v2/theme';
+
+import useStyles from './styles';
+
+const mapStyles = {
+ default: mapStyle,
+ hover: mapStyle,
+ pressed: mapStyle,
+};
+
+const NodesMap = () => {
+ const classes = useStyles();
+ const {mapMarkers} = NodesStore;
+
+ const mapConfig = {
+ projection: {
+ scale: 85,
+ rotation: [-11, 0, 0],
+ },
+ style: {
+ width: '100%',
+ height: 'auto',
+ },
+ center: [0, 20],
+ };
+
+ const renderMarker = marker => (
+
+ (
+ <>
+ NODE: {marker.name}
+ Gossip: {marker.gossip}
+ >
+ )}
+ >
+
+
+
+ );
+ return (
+
+ Nodes Map
+
+
+
+ {(geographies, projection) =>
+ geographies.map(
+ (geography, i) =>
+ geography.id !== 'ATA' && (
+
+ ),
+ )
+ }
+
+ {map(renderMarker)(mapMarkers)}
+
+
+
+ );
+};
+
+export default observer(NodesMap);
diff --git a/src/v2/components/Dashboard/NetworkOverview/NodesMap/styles.js b/src/v2/components/Dashboard/NetworkOverview/NodesMap/styles.js
new file mode 100644
index 00000000..d410663d
--- /dev/null
+++ b/src/v2/components/Dashboard/NetworkOverview/NodesMap/styles.js
@@ -0,0 +1,28 @@
+import {makeStyles} from '@material-ui/core';
+import getColor from 'v2/utils/getColor';
+
+export default makeStyles(theme => ({
+ card: {
+ background: getColor('grey2')(theme),
+ maxHeight: 290,
+ overflow: 'hidden',
+ padding: '14px 35px',
+ },
+ tooltip: {
+ background: '#fff',
+ color: getColor('dark')(theme),
+ padding: 10,
+ borderRadius: 0,
+ },
+ tooltipTitle: {
+ fontSize: 15,
+ marginBottom: 4,
+ textOverflow: 'ellipsis',
+ whiteSpace: 'nowrap',
+ overflow: 'hidden',
+ },
+ tooltipDesc: {
+ fontSize: 12,
+ color: getColor('grey3')(theme),
+ },
+}));
diff --git a/src/v2/components/Dashboard/NetworkOverview/StatCards/index.jsx b/src/v2/components/Dashboard/NetworkOverview/StatCards/index.jsx
index b2ac5815..5e893885 100644
--- a/src/v2/components/Dashboard/NetworkOverview/StatCards/index.jsx
+++ b/src/v2/components/Dashboard/NetworkOverview/StatCards/index.jsx
@@ -2,75 +2,39 @@
import React from 'react';
import {observer} from 'mobx-react-lite';
-import {Grid, Paper, Typography} from '@material-ui/core';
+import {map} from 'lodash/fp';
+import {Grid, Typography} from '@material-ui/core';
+import Card from 'v2/components/UI/StatCard';
import OverviewStore from 'v2/stores/networkOverview';
+import NodesStore from 'v2/stores/nodes';
import useStyles from './styles';
const StatCards = () => {
- const {globalStats} = OverviewStore;
+ const {globalStats, statsChanges} = OverviewStore;
+ const {cluster, clusterChanges} = NodesStore;
const classes = useStyles();
- return (
-
-
-
-
- Node Count
-
-
- {globalStats['!blkLastSlot']}
- {' '}
-
- -2.45%
-
-
-
-
-
-
- Block Height
-
-
- {globalStats['!blkLastSlot']}
-
-
- -2.45%
-
-
-
-
-
-
- Transactions Count
-
-
- {globalStats['!txnCount']}
-
-
- -2.45%
-
-
-
-
-
-
- Current Leader
-
+
+ const cards = [
+ {
+ title: 'Node Count',
+ value: cluster.nodes.length,
+ changes: clusterChanges.nodes,
+ },
+ {
+ title: 'Block Height',
+ value: globalStats['!blkLastSlot'],
+ changes: statsChanges['!blkLastSlot'],
+ },
+ {
+ title: 'Transactions Count',
+ value: globalStats['!txnCount'],
+ changes: statsChanges['!txnCount'],
+ },
+ {
+ title: 'Current Leader',
+ value() {
+ return (
{
>
{globalStats['!entLastLeader']}
-
-
+ );
+ },
+ },
+ ];
+
+ const renderStats = ({
+ title,
+ value,
+ changes = null,
+ }: {
+ title: string,
+ value: string | (() => React$Node),
+ changes?: string,
+ }) => (
+
+
+
+ );
+
+ return (
+
+ {map(renderStats)(cards)}
);
};
diff --git a/src/v2/components/Dashboard/NetworkOverview/StatCards/styles.js b/src/v2/components/Dashboard/NetworkOverview/StatCards/styles.js
index 019297ca..8d71892f 100644
--- a/src/v2/components/Dashboard/NetworkOverview/StatCards/styles.js
+++ b/src/v2/components/Dashboard/NetworkOverview/StatCards/styles.js
@@ -1,6 +1,5 @@
import {makeStyles} from '@material-ui/core';
-
-import getColor from '../../../../utils/getColor';
+import getColor from 'v2/utils/getColor';
export default makeStyles(theme => ({
card: {
diff --git a/src/v2/components/Dashboard/NetworkOverview/TPS/index.jsx b/src/v2/components/Dashboard/NetworkOverview/TPS/index.jsx
new file mode 100644
index 00000000..7f8c905e
--- /dev/null
+++ b/src/v2/components/Dashboard/NetworkOverview/TPS/index.jsx
@@ -0,0 +1,86 @@
+// @flow
+
+import {Typography} from '@material-ui/core';
+import {maxBy, minBy, get} from 'lodash/fp';
+import React from 'react';
+import {observer} from 'mobx-react-lite';
+import {ResponsiveLine} from '@nivo/line';
+import OverviewStore from 'v2/stores/networkOverview';
+
+import useStyles from './styles';
+
+type Point = {
+ data: {
+ x: string,
+ y: number,
+ date: string,
+ },
+};
+
+const Tooltip = ({point: {data}}: {point: Point}) => {
+ const classes = useStyles();
+ if (!data) return null;
+ return (
+
+
AVG TPS:{data.y}
+
{data.date}
+
+ );
+};
+
+const TPS = () => {
+ const classes = useStyles();
+ const {txnChartData, globalStats, statsChanges} = OverviewStore;
+ const data = [
+ {
+ id: 'txn',
+ data: txnChartData,
+ },
+ ];
+
+ const min = get('y')(minBy('y')(txnChartData));
+ const max = get('y')(maxBy('y')(txnChartData));
+
+ const lineProperties = {
+ animate: true,
+ useMesh: true,
+ layers: ['lines', 'mesh'],
+ yScale: {
+ type: 'linear',
+ stacked: false,
+ min,
+ max,
+ },
+ xScale: {
+ type: 'time',
+ format: '%Y%m%dT%H:%M',
+ precision: 'minute',
+ },
+ colors: ['#00FFAD'],
+ curve: 'monotoneX',
+ data,
+ };
+
+ return (
+
+
Current TPS
+
+
+ {globalStats.tpsCount || 0}
+
+ {statsChanges && (
+
+ {statsChanges.tpsCount}%
+
+ )}
+
+
+ {Boolean(txnChartData.length) && (
+
+ )}
+
+
+ );
+};
+
+export default observer(TPS);
diff --git a/src/v2/components/Dashboard/NetworkOverview/TPS/styles.js b/src/v2/components/Dashboard/NetworkOverview/TPS/styles.js
new file mode 100644
index 00000000..8bcc3b69
--- /dev/null
+++ b/src/v2/components/Dashboard/NetworkOverview/TPS/styles.js
@@ -0,0 +1,43 @@
+import {makeStyles} from '@material-ui/core';
+import getColor from 'v2/utils/getColor';
+
+export default makeStyles(theme => ({
+ card: {
+ background: getColor('grey2')(theme),
+ padding: '14px 35px',
+ height: '100%',
+ },
+ graph: {
+ textAlign: 'center',
+ height: 89,
+ },
+ tooltip: {
+ backgroundColor: '#fff',
+ padding: 13,
+ color: getColor('dark')(theme),
+ textAlign: 'center',
+ },
+ tooltipDate: {
+ fontSize: 12,
+ color: getColor('grey3')(theme),
+ },
+ tooltipTitle: {
+ textTransform: 'uppercase',
+ },
+ values: {
+ display: 'flex',
+ alignItems: 'flex-start',
+ justifyContent: 'space-between',
+ },
+ val: {
+ fontSize: 60,
+ fontWeight: 'bold',
+ color: getColor('main')(theme),
+ margin: '20px 0',
+ },
+ changes: {
+ fontSize: 18,
+ fontWeight: 'bold',
+ marginTop: 20,
+ },
+}));
diff --git a/src/v2/components/Dashboard/NetworkOverview/index.jsx b/src/v2/components/Dashboard/NetworkOverview/index.jsx
index c4df04e8..6aeb8acd 100644
--- a/src/v2/components/Dashboard/NetworkOverview/index.jsx
+++ b/src/v2/components/Dashboard/NetworkOverview/index.jsx
@@ -1,25 +1,51 @@
// @flow
-import {Typography, Container} from '@material-ui/core';
-import React, {useEffect} from 'react';
+import {Grid, Container} from '@material-ui/core';
+import React, {useEffect, useRef} from 'react';
import OverviewStore from 'v2/stores/networkOverview';
+import SectionHeader from 'v2/components/UI/SectionHeader';
+
import StatCards from './StatCards';
+import TPS from './TPS';
+import NodesMap from './NodesMap';
import useStyles from './styles';
-import decor from 'v2/assets/img/decorate.png';
const NetworkOverview = () => {
- const {getStats} = OverviewStore;
+ const {getStats, getTxnStats} = OverviewStore;
const classes = useStyles();
+ const timeout = useRef(null);
+
+ const pollStats = () => {
+ timeout.current = setTimeout(() => {
+ try {
+ getTxnStats();
+ } finally {
+ pollStats();
+ }
+ }, 5000);
+ };
+
useEffect(() => {
getStats();
- }, [getStats]);
+ getTxnStats();
+ pollStats();
+ return () => {
+ clearTimeout(timeout.current);
+ };
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
return (
-
-
- Network overview
-
+
Network Overview
+
+
+
+
+
+
+
+
diff --git a/src/v2/components/Dashboard/NetworkOverview/styles.js b/src/v2/components/Dashboard/NetworkOverview/styles.js
index 2aadb0c7..db9cb860 100644
--- a/src/v2/components/Dashboard/NetworkOverview/styles.js
+++ b/src/v2/components/Dashboard/NetworkOverview/styles.js
@@ -5,12 +5,7 @@ export default makeStyles({
padding: '40px 0',
position: 'relative',
},
- title: {
- marginBottom: 47,
- },
- decor: {
- position: 'absolute',
- left: -120,
- top: 32,
+ row: {
+ marginBottom: 8,
},
});
diff --git a/src/v2/components/Dashboard/ViewAll/index.jsx b/src/v2/components/Dashboard/ViewAll/index.jsx
index 934fc2b5..35159e5a 100644
--- a/src/v2/components/Dashboard/ViewAll/index.jsx
+++ b/src/v2/components/Dashboard/ViewAll/index.jsx
@@ -1,33 +1,30 @@
// @flow
-import {Container, Grid, Typography} from '@material-ui/core';
+import {Container, Grid} from '@material-ui/core';
import React from 'react';
import Button from 'v2/components/UI/Button';
-import decor from 'v2/assets/img/decorate.png';
+import SectionHeader from 'v2/components/UI/SectionHeader';
import useStyles from './styles';
-const ViewAll = props => {
+const ViewAll = () => {
const classes = useStyles();
return (
-
-
- view all
-
+
View All
-
-
+
View all applications
-
+
View all blocks
diff --git a/src/v2/components/Dashboard/index.jsx b/src/v2/components/Dashboard/index.jsx
index dad9d996..dd7392ef 100644
--- a/src/v2/components/Dashboard/index.jsx
+++ b/src/v2/components/Dashboard/index.jsx
@@ -1,5 +1,6 @@
import React from 'react';
import NetworkOverview from 'v2/components/Dashboard/NetworkOverview';
+
import ViewAll from './ViewAll';
const Dashboard = () => {
diff --git a/src/v2/components/Footer/Newsletter/index.jsx b/src/v2/components/Footer/Newsletter/index.jsx
new file mode 100644
index 00000000..49758411
--- /dev/null
+++ b/src/v2/components/Footer/Newsletter/index.jsx
@@ -0,0 +1,31 @@
+import {InputBase, Typography} from '@material-ui/core';
+import React from 'react';
+
+import useStyles from './styles';
+
+const Newsletter = () => {
+ const classes = useStyles();
+ return (
+
+
+ Join the Newsletter
+
+
+ Stay up to date with the latest Solana news.
+
+
+
+ );
+};
+
+export default Newsletter;
diff --git a/src/v2/components/Footer/Newsletter/styles.js b/src/v2/components/Footer/Newsletter/styles.js
new file mode 100644
index 00000000..5c6c7737
--- /dev/null
+++ b/src/v2/components/Footer/Newsletter/styles.js
@@ -0,0 +1,40 @@
+import {makeStyles} from '@material-ui/core';
+import {fade} from '@material-ui/core/styles';
+import getColor from 'v2/utils/getColor';
+
+export default makeStyles(theme => ({
+ title: {
+ marginTop: 38,
+ color: getColor('dark')(theme),
+ marginBottom: 15,
+ },
+ desc: {
+ color: getColor('dark')(theme),
+ fontSize: 15,
+ lineHeight: '24px',
+ maxWidth: 225,
+ marginBottom: 20,
+ },
+ form: {
+ border: `1px solid ${fade(getColor('dark')(theme), 0.3)}`,
+ padding: 5,
+ display: 'flex',
+ marginBottom: 132,
+ },
+ input: {
+ border: 'none',
+ background: getColor('grey2')(theme),
+ height: 40,
+ width: '100%',
+ padding: '0 20px',
+ fontSize: 12,
+ },
+ btn: {
+ background: getColor('main')(theme),
+ border: `1px solid ${getColor('grey2')(theme)}`,
+ fontSize: 12,
+ fontWeight: '600',
+ textTransform: 'uppercase',
+ padding: '5px 14px',
+ },
+}));
diff --git a/src/v2/components/Footer/Partnership/index.jsx b/src/v2/components/Footer/Partnership/index.jsx
new file mode 100644
index 00000000..e296ff7b
--- /dev/null
+++ b/src/v2/components/Footer/Partnership/index.jsx
@@ -0,0 +1,37 @@
+import {Typography} from '@material-ui/core';
+import React from 'react';
+import Button from 'v2/components/UI/Button';
+import iconRight from 'v2/assets/icons/arrow-right.png';
+
+import useStyles from './styles';
+
+const Partnership = () => {
+ const classes = useStyles();
+ return (
+
+
+ Partnership
+
+
+ Looking to scale your business?
+
+ Let’s build something together.
+
+
+ Partner with us
+
+
+
+ );
+};
+
+export default Partnership;
diff --git a/src/v2/components/Footer/Partnership/styles.js b/src/v2/components/Footer/Partnership/styles.js
new file mode 100644
index 00000000..6999dc80
--- /dev/null
+++ b/src/v2/components/Footer/Partnership/styles.js
@@ -0,0 +1,31 @@
+import {makeStyles} from '@material-ui/core';
+
+export default makeStyles({
+ title: {
+ marginBottom: 15,
+ },
+ desc: {
+ fontSize: 15,
+ lineHeight: '24px',
+ marginBottom: 23,
+ },
+ links: {
+ marginTop: 43,
+ '& a': {
+ display: 'flex',
+ alignItems: 'center',
+ textDecoration: 'none',
+ textTransform: 'uppercase',
+ fontWeight: 'bold',
+ fontSize: 11,
+ letterSpacing: 3.2,
+ color: '#fff',
+ marginBottom: 21,
+ width: 250,
+ justifyContent: 'space-between',
+ '& img': {
+ marginLeft: 10,
+ },
+ },
+ },
+});
diff --git a/src/v2/components/Footer/assets/bg.svg b/src/v2/components/Footer/assets/bg.svg
new file mode 100644
index 00000000..2fc1c9f8
--- /dev/null
+++ b/src/v2/components/Footer/assets/bg.svg
@@ -0,0 +1,35 @@
+
diff --git a/src/v2/components/Footer/index.jsx b/src/v2/components/Footer/index.jsx
new file mode 100644
index 00000000..7dc3b341
--- /dev/null
+++ b/src/v2/components/Footer/index.jsx
@@ -0,0 +1,35 @@
+import {Grid, Typography} from '@material-ui/core';
+import React from 'react';
+import Logo from 'v2/components/UI/Logo';
+
+import Social from '../Social';
+import Newsletter from './Newsletter';
+import Partnership from './Partnership';
+import useStyles from './styles';
+import bg from './assets/bg.svg';
+
+const Footer = () => {
+ const classes = useStyles();
+ return (
+
+
+
+
+
+
+
+ © Copyright Solana Labs, Inc. All rights reserved.
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default Footer;
diff --git a/src/v2/components/Footer/styles.js b/src/v2/components/Footer/styles.js
new file mode 100644
index 00000000..24097c2d
--- /dev/null
+++ b/src/v2/components/Footer/styles.js
@@ -0,0 +1,29 @@
+import {makeStyles} from '@material-ui/core';
+import getColor from 'v2/utils/getColor';
+
+export default makeStyles(theme => ({
+ root: {
+ paddingTop: 100,
+ position: 'relative',
+ marginLeft: 28,
+ },
+ left: {
+ background: getColor('main')(theme),
+ padding: '45px 80px 35px',
+ display: 'flex',
+ flexDirection: 'column',
+ },
+ right: {
+ background: getColor('grey2')(theme),
+ padding: '170px 80px 35px',
+ },
+ copyright: {
+ marginTop: 'auto',
+ fontSize: 10,
+ color: getColor('dark')(theme),
+ },
+ bg: {
+ position: 'absolute',
+ left: -160,
+ },
+}));
diff --git a/src/v2/components/Header/index.jsx b/src/v2/components/Header/index.jsx
index a2e9e940..c02f809d 100644
--- a/src/v2/components/Header/index.jsx
+++ b/src/v2/components/Header/index.jsx
@@ -22,7 +22,7 @@ const Header = () => {
Real-time updated:
- Live
+ Every 5 sec
diff --git a/src/v2/components/Header/styles.js b/src/v2/components/Header/styles.js
index 306e6d0b..d8d162a4 100644
--- a/src/v2/components/Header/styles.js
+++ b/src/v2/components/Header/styles.js
@@ -1,7 +1,6 @@
import {makeStyles} from '@material-ui/core';
import {fade} from '@material-ui/core/styles';
-
-import getColor from '../../utils/getColor';
+import getColor from 'v2/utils/getColor';
export default makeStyles(theme => ({
root: {
diff --git a/src/v2/components/NavBar/index.jsx b/src/v2/components/NavBar/index.jsx
index ac512405..93a519b3 100644
--- a/src/v2/components/NavBar/index.jsx
+++ b/src/v2/components/NavBar/index.jsx
@@ -1,10 +1,10 @@
// @flow
import {Drawer, List, ListItem, ListItemIcon} from '@material-ui/core';
-import {withRouter} from 'react-router-dom';
-import type {ContextRouter} from 'react-router-dom';
+import {RouterHistory, withRouter} from 'react-router-dom';
import React from 'react';
import {map, propEq, eq} from 'lodash/fp';
+
import {ReactComponent as dashboard} from './assets/dashboard.svg';
import {ReactComponent as transactions} from './assets/transactions.svg';
import {ReactComponent as validators} from './assets/validators.svg';
@@ -12,7 +12,6 @@ import {ReactComponent as tourDeSol} from './assets/tour-de-sol.svg';
import {ReactComponent as applications} from './assets/applications.svg';
import {ReactComponent as blocks} from './assets/blocks.svg';
import {ReactComponent as favorites} from './assets/favorites.svg';
-
import useStyles from './styles';
const icons = {
@@ -25,7 +24,13 @@ const icons = {
favorites,
};
-const NavBar = ({location, history}: ContextRouter) => {
+const NavBar = ({
+ location,
+ history,
+}: {
+ location: Location,
+ history: RouterHistory,
+}) => {
const classes = useStyles();
const routes = [
'dashboard',
@@ -42,7 +47,7 @@ const NavBar = ({location, history}: ContextRouter) => {
const selected =
propEq('pathname', `/${link}`)(location) ||
(propEq('pathname', '/')(location) && isDashboard);
- const changeRoute = () => history.push(`/${isDashboard ? '' : link}`);
+ const changeRoute = () => history.push(`/v2/${isDashboard ? '' : link}`);
return (
+
+
diff --git a/src/v2/components/Social/assets/medium.svg b/src/v2/components/Social/assets/medium.svg
new file mode 100644
index 00000000..5a427fca
--- /dev/null
+++ b/src/v2/components/Social/assets/medium.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/v2/components/Social/assets/reddit.svg b/src/v2/components/Social/assets/reddit.svg
new file mode 100644
index 00000000..cfa0ec47
--- /dev/null
+++ b/src/v2/components/Social/assets/reddit.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/v2/components/Social/assets/telegram.svg b/src/v2/components/Social/assets/telegram.svg
new file mode 100644
index 00000000..6476f72a
--- /dev/null
+++ b/src/v2/components/Social/assets/telegram.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/v2/components/Social/assets/twitter.svg b/src/v2/components/Social/assets/twitter.svg
new file mode 100644
index 00000000..c3288d61
--- /dev/null
+++ b/src/v2/components/Social/assets/twitter.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/v2/components/Social/index.jsx b/src/v2/components/Social/index.jsx
new file mode 100644
index 00000000..8d3d4a07
--- /dev/null
+++ b/src/v2/components/Social/index.jsx
@@ -0,0 +1,56 @@
+// @flow
+import React from 'react';
+import {map} from 'lodash/fp';
+
+import {ReactComponent as discord} from './assets/discord.svg';
+import {ReactComponent as medium} from './assets/medium.svg';
+import {ReactComponent as reddit} from './assets/reddit.svg';
+import {ReactComponent as telegram} from './assets/telegram.svg';
+import {ReactComponent as twitter} from './assets/twitter.svg';
+import useStyles from './styles';
+
+type Link = {
+ link: string,
+ icon: React$Node,
+ name: string,
+};
+
+const links: Link[] = [
+ {
+ link: '#',
+ icon: discord,
+ name: 'discord',
+ },
+ {
+ link: '#',
+ icon: telegram,
+ name: 'telegram',
+ },
+ {
+ link: '#',
+ icon: reddit,
+ name: 'reddit',
+ },
+ {
+ link: '#',
+ icon: twitter,
+ name: 'twitter',
+ },
+ {
+ link: '#',
+ icon: medium,
+ name: 'medium',
+ },
+];
+const Social = () => {
+ const classes = useStyles();
+ const renderLink = ({name, link, icon: Icon}: Link) => (
+
+
+
+ );
+
+ return {map(renderLink)(links)}
;
+};
+
+export default Social;
diff --git a/src/v2/components/Social/styles.js b/src/v2/components/Social/styles.js
new file mode 100644
index 00000000..b7e54dcc
--- /dev/null
+++ b/src/v2/components/Social/styles.js
@@ -0,0 +1,24 @@
+import {makeStyles} from '@material-ui/core';
+import getColor from 'v2/utils/getColor';
+
+export default makeStyles(theme => ({
+ list: {
+ display: 'flex',
+ flexDirection: 'column',
+ alignItems: 'center',
+ marginTop: 80,
+ },
+ link: {
+ background: getColor('main')(theme),
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ width: 30,
+ height: 30,
+ marginBottom: 22,
+ '& svg': {
+ width: 17,
+ height: 'auto',
+ },
+ },
+}));
diff --git a/src/v2/components/UI/Button/index.jsx b/src/v2/components/UI/Button/index.jsx
index f8b04677..744eca86 100644
--- a/src/v2/components/UI/Button/index.jsx
+++ b/src/v2/components/UI/Button/index.jsx
@@ -2,14 +2,15 @@
import React from 'react';
import {Button as BaseButton} from '@material-ui/core';
import cn from 'classnames';
+
import useStyles from './styles';
type ButtonProps = {
color: string,
- fullWidth: boolean,
+ fullWidth?: boolean,
};
-const Button = ({color, fullWidth, ...props}: ButtonProps) => {
+const Button = ({color, fullWidth = false, ...props}: ButtonProps) => {
const classes = useStyles();
return (
({
borderColor: getColor('main')(theme),
'& button': {
borderRadius: 0,
- padding: '12px 25px',
'&:hover': {
backgroundColor: fade(getColor('main')(theme), 0.8),
},
diff --git a/src/v2/components/UI/Logo/assets/logo_vertical.svg b/src/v2/components/UI/Logo/assets/logo_vertical.svg
new file mode 100644
index 00000000..9dc431b8
--- /dev/null
+++ b/src/v2/components/UI/Logo/assets/logo_vertical.svg
@@ -0,0 +1,9 @@
+
diff --git a/src/v2/components/UI/Logo/index.jsx b/src/v2/components/UI/Logo/index.jsx
index 3055f6ef..6c60ae8b 100644
--- a/src/v2/components/UI/Logo/index.jsx
+++ b/src/v2/components/UI/Logo/index.jsx
@@ -2,10 +2,15 @@
import React from 'react';
import logo from './assets/logo.svg';
+import logoVertical from './assets/logo_vertical.svg';
-const Logo = () => (
+type LogoProps = {
+ vertical?: boolean,
+};
+
+const Logo = ({vertical = false}: LogoProps) => (
-
+
);
diff --git a/src/v2/components/UI/MapTooltip/index.jsx b/src/v2/components/UI/MapTooltip/index.jsx
new file mode 100644
index 00000000..5c0fd0a2
--- /dev/null
+++ b/src/v2/components/UI/MapTooltip/index.jsx
@@ -0,0 +1,29 @@
+// @flow
+import {Tooltip} from '@material-ui/core';
+import {TooltipProps} from '@material-ui/core/Tooltip';
+import React from 'react';
+
+import useStyles from './styles';
+
+type MapTooltipProps = {
+ title: string,
+};
+
+const MapTooltip = ({title, ...rest}: MapTooltipProps & TooltipProps) => {
+ const {arrow, ...classes} = useStyles();
+
+ return (
+
+ {title()}
+
+ >
+ }
+ />
+ );
+};
+
+export default MapTooltip;
diff --git a/src/v2/components/UI/MapTooltip/styles.js b/src/v2/components/UI/MapTooltip/styles.js
new file mode 100644
index 00000000..18ab6f34
--- /dev/null
+++ b/src/v2/components/UI/MapTooltip/styles.js
@@ -0,0 +1,55 @@
+import {makeStyles} from '@material-ui/core';
+
+function arrowGenerator(color) {
+ return {
+ '&[x-placement*="bottom"] $arrow': {
+ top: 0,
+ left: 0,
+ marginTop: '-0.95em',
+ width: '3em',
+ height: '1em',
+ '&::before': {
+ borderWidth: '0 1em 1em 1em',
+ borderColor: `transparent transparent ${color} transparent`,
+ },
+ },
+ '&[x-placement*="top"] $arrow': {
+ bottom: 0,
+ left: 0,
+ marginBottom: '-0.95em',
+ width: '3em',
+ height: '1em',
+ '&::before': {
+ borderWidth: '1em 1em 0 1em',
+ borderColor: `${color} transparent transparent transparent`,
+ },
+ },
+ '&[x-placement*="right"] $arrow': {
+ left: 0,
+ marginLeft: '-0.95em',
+ height: '3em',
+ width: '1em',
+ '&::before': {
+ borderWidth: '1em 1em 1em 0',
+ borderColor: `transparent ${color} transparent transparent`,
+ },
+ },
+ '&[x-placement*="left"] $arrow': {
+ right: 0,
+ marginRight: '-0.95em',
+ height: '3em',
+ width: '1em',
+ '&::before': {
+ borderWidth: '1em 0 1em 1em',
+ borderColor: `transparent transparent transparent ${color}`,
+ },
+ },
+ };
+}
+
+export default makeStyles(theme => ({
+ tooltip: {
+ position: 'relative',
+ },
+ popper: arrowGenerator(theme.palette.grey[700]),
+}));
diff --git a/src/v2/assets/img/decorate.png b/src/v2/components/UI/SectionHeader/assets/decorate.png
similarity index 100%
rename from src/v2/assets/img/decorate.png
rename to src/v2/components/UI/SectionHeader/assets/decorate.png
diff --git a/src/v2/components/UI/SectionHeader/index.jsx b/src/v2/components/UI/SectionHeader/index.jsx
new file mode 100644
index 00000000..fabfd6f6
--- /dev/null
+++ b/src/v2/components/UI/SectionHeader/index.jsx
@@ -0,0 +1,20 @@
+// @flow
+import {Typography} from '@material-ui/core';
+import React from 'react';
+
+import decor from './assets/decorate.png';
+import useStyles from './styles';
+
+const SectionHeader = ({children}: {children: React$Node}) => {
+ const classes = useStyles();
+ return (
+
+
+
+ {children}
+
+
+ );
+};
+
+export default SectionHeader;
diff --git a/src/v2/components/UI/SectionHeader/styles.js b/src/v2/components/UI/SectionHeader/styles.js
new file mode 100644
index 00000000..72a50802
--- /dev/null
+++ b/src/v2/components/UI/SectionHeader/styles.js
@@ -0,0 +1,17 @@
+import {makeStyles} from '@material-ui/core';
+
+export default makeStyles({
+ root: {
+ position: 'relative',
+ marginBottom: 47,
+ },
+ title: {
+ display: 'flex',
+ alignItems: 'center',
+ },
+ decor: {
+ position: 'absolute',
+ left: -120,
+ top: -7,
+ },
+});
diff --git a/src/v2/components/UI/StatCard/index.jsx b/src/v2/components/UI/StatCard/index.jsx
new file mode 100644
index 00000000..22566607
--- /dev/null
+++ b/src/v2/components/UI/StatCard/index.jsx
@@ -0,0 +1,46 @@
+// @flow
+import React from 'react';
+import {Paper, Typography} from '@material-ui/core';
+
+import useStyles from './styles';
+
+type StatCardProps = {
+ title?: string,
+ value?: string | (() => React$Node),
+ changes?: string | (() => React$Node),
+};
+
+const StatCard = (props: StatCardProps) => {
+ const classes = useStyles();
+ const {title, value, changes} = props;
+ const renderValue = () => {
+ if (typeof value === 'function') {
+ return value();
+ }
+ return (
+
+ {value}
+
+ );
+ };
+ const renderChanges = () => {
+ if (!changes) return null;
+ if (typeof changes === 'function') {
+ return changes();
+ }
+ return {changes}%;
+ };
+ return (
+
+
+ {title}
+
+ {renderValue()}
+
+ {renderChanges()}
+
+
+ );
+};
+
+export default StatCard;
diff --git a/src/v2/components/UI/StatCard/styles.js b/src/v2/components/UI/StatCard/styles.js
new file mode 100644
index 00000000..4a4b30ee
--- /dev/null
+++ b/src/v2/components/UI/StatCard/styles.js
@@ -0,0 +1,24 @@
+import {makeStyles} from '@material-ui/core';
+import getColor from 'v2/utils/getColor';
+
+export default makeStyles(theme => ({
+ root: {
+ background: getColor('grey')(theme),
+ color: '#fff',
+ borderRadius: 0,
+ height: '100%',
+ padding: '17px 30px',
+ },
+ value: {
+ fontSize: 60,
+ fontWeight: 'bold',
+ color: getColor('main')(theme),
+ margin: '20px 0',
+ },
+ changes: {
+ display: 'flex',
+ justifyContent: 'center',
+ fontSize: 18,
+ fontWeight: 'bold',
+ },
+}));
diff --git a/src/v2/const.js b/src/v2/const.js
index 23bae4d2..aa410977 100644
--- a/src/v2/const.js
+++ b/src/v2/const.js
@@ -1,2 +1,3 @@
-export const BLOCK_EXPLORER_API_BASE = `${process.env.REACT_APP_BASE_URL}:3001`;
-export const BLOCK_EXPLORER_RPC_URL = `${process.env.REACT_APP_BASE_URL}:8899`;
+export const BLOCK_EXPLORER_API_BASE = `http://${process.env.REACT_APP_BASE_URL}:3001`;
+export const BLOCK_EXPLORER_WS_API_BASE = `ws://${process.env.REACT_APP_BASE_URL}:3001`;
+export const BLOCK_EXPLORER_RPC_URL = `http://${process.env.REACT_APP_BASE_URL}:8899`;
diff --git a/src/v2/stores/networkOverview.js b/src/v2/stores/networkOverview.js
index 00bd89a5..17431a9b 100644
--- a/src/v2/stores/networkOverview.js
+++ b/src/v2/stores/networkOverview.js
@@ -1,29 +1,114 @@
-import {configure, flow, observable, action} from 'mobx';
+import {
+ configure,
+ flow,
+ observable,
+ action,
+ decorate,
+ observe,
+ computed,
+} from 'mobx';
+import {parse, format} from 'date-fns';
+import {
+ map,
+ keys,
+ compose,
+ pick,
+ mapValues,
+ toPairs,
+ find,
+ includes,
+ identity,
+ pickBy,
+} from 'lodash/fp';
+import {camelizeKeys} from 'humps';
import * as API from 'v2/api/stats';
+import {parseBlock, parseTransaction} from 'v2/utils/parseMessage';
-configure({enforceActions: 'always'});
-
-const OverviewStore = observable(
- {
- state: 'pending',
- globalStats: {},
-
- getStats: flow(function* getStats() {
- this.state = 'loading';
- try {
- const res = yield API.getStats();
- this.state = 'loaded';
- this.globalStats = res.data;
- } catch (e) {
- this.state = 'error';
+import calcChanges from '../utils/calcChanges';
+
+configure({enforceActions: 'observed'});
+
+class OverviewStore {
+ globalStats = {};
+ statsChanges = {};
+ txnStats = {};
+
+ constructor() {
+ observe(this, 'globalStats', ({oldValue, newValue}) => {
+ if (!keys(oldValue).length) {
+ return;
}
- }),
- },
- {
- state: observable,
- globalStats: observable,
- getStats: action.bound,
- },
-);
-
-export default OverviewStore;
+
+ this.statsChanges = compose(
+ mapValues.convert({cap: false})((value, key) =>
+ calcChanges(oldValue[key], value),
+ ),
+ pick(['!blkLastSlot', '!txnCount', 'tpsCount']),
+ )(newValue);
+ });
+ }
+
+ addBlock = block => {
+ parseBlock(block);
+ };
+
+ addTransaction = block => {
+ parseTransaction(block);
+ };
+
+ updateGlobalStats = data => {
+ const parsedData = camelizeKeys(JSON.parse(data));
+ const tpsCountField = compose(
+ find(includes('txnPerSec:')),
+ keys,
+ )(parsedData);
+ this.globalStats = {
+ ...parsedData,
+ tpsCount: parsedData[tpsCountField],
+ };
+ };
+
+ get txnChartData() {
+ return compose(
+ map(([date, value = 0]) => ({
+ y: Math.round((parseFloat(value) / 60) * 100) / 100,
+ x: date,
+ date: format(parse(date), 'MMM D hh:mmA'),
+ })),
+ toPairs,
+ pickBy(identity),
+ )(this.txnStats);
+ }
+
+ getStats = flow(function* getStats() {
+ const res = yield API.getStats();
+ const tpsCountField = compose(
+ find(includes('txnPerSec:')),
+ keys,
+ )(res.data);
+ this.globalStats = {
+ ...res.data,
+ tpsCount: res.data[tpsCountField],
+ };
+ return res;
+ });
+
+ getTxnStats = flow(function* getTxnStats() {
+ const res = yield API.getTxnStats();
+ this.txnStats = res.data;
+ return res;
+ });
+}
+
+decorate(OverviewStore, {
+ globalStats: observable,
+ getStats: action.bound,
+ getTxnStats: action.bound,
+ txnChartData: computed,
+ txnStats: observable,
+ addBlock: action,
+ addTransaction: action,
+ updateGlobalStats: action,
+});
+
+export default new OverviewStore();
diff --git a/src/v2/stores/nodes.js b/src/v2/stores/nodes.js
new file mode 100644
index 00000000..e48d9785
--- /dev/null
+++ b/src/v2/stores/nodes.js
@@ -0,0 +1,51 @@
+import {eq, compose, keys, map, mapValues, pick} from 'lodash/fp';
+import {action, computed, decorate, observable, observe} from 'mobx';
+import {parseClusterInfo} from 'v2/utils/parseMessage';
+
+import calcChanges from '../utils/calcChanges';
+
+class NodesStore {
+ nodes = [];
+ cluster = {
+ nodes: [],
+ };
+ clusterChanges = {};
+
+ constructor() {
+ observe(this, 'cluster', ({oldValue, newValue}) => {
+ if (!keys(oldValue).length) {
+ return;
+ }
+ this.clusterChanges = compose(
+ mapValues.convert({cap: false})((value, key) => {
+ if (eq('nodes', key)) {
+ return calcChanges(oldValue[key].length, value.length);
+ }
+ return calcChanges(oldValue[key], value);
+ }),
+ pick(['nodes', 'supply']),
+ )(newValue);
+ });
+ }
+
+ updateClusterInfo = data => {
+ this.cluster = parseClusterInfo(data);
+ };
+
+ get mapMarkers() {
+ return map(({pubkey: name, gossip, lat, lng}) => ({
+ name,
+ gossip,
+ coordinates: [lng, lat],
+ }))(this.cluster.nodes);
+ }
+}
+
+decorate(NodesStore, {
+ nodes: observable,
+ cluster: observable,
+ updateClusterInfo: action.bound,
+ mapMarkers: computed,
+});
+
+export default new NodesStore();
diff --git a/src/v2/stores/socket.js b/src/v2/stores/socket.js
new file mode 100644
index 00000000..180a8186
--- /dev/null
+++ b/src/v2/stores/socket.js
@@ -0,0 +1,22 @@
+import {initSocket} from 'v2/api/socket';
+import networkOverview from 'v2/stores/networkOverview';
+import nodes from 'v2/stores/nodes';
+
+const socketActions = {
+ actions: {
+ 'global-info': networkOverview.updateGlobalStats,
+ blk: networkOverview.addBlock,
+ 'cluster-info': nodes.updateClusterInfo,
+ 'txns-by-prgid': networkOverview.addTransaction,
+ },
+ onMessage(event) {
+ const {t, m} = JSON.parse(event.data);
+ this.actions[t](m);
+ },
+ init() {
+ this.ws = initSocket();
+ this.ws.onmessage = event => this.onMessage(event);
+ },
+};
+
+export default socketActions;
diff --git a/src/v2/theme.js b/src/v2/theme.js
index a907482e..23604f7d 100644
--- a/src/v2/theme.js
+++ b/src/v2/theme.js
@@ -8,6 +8,7 @@ export default createMuiTheme({
grey: '#242424',
grey2: '#202020',
grey3: '#979797',
+ grey4: '#c4c4c4',
main: '#00FFAD',
},
secondary: {
@@ -27,6 +28,11 @@ export default createMuiTheme({
lineHeight: '31px',
letterSpacing: 2.5,
},
+ h5: {
+ fontWeight: 'bold',
+ fontSize: 19,
+ letterSpacing: 0.4,
+ },
button: {
textTransform: 'uppercase',
fontSize: 15,
@@ -35,3 +41,16 @@ export default createMuiTheme({
},
},
});
+
+export const mapStyle = {
+ fill: '#202020',
+ stroke: '#fff',
+ strokeWidth: 0.5,
+ outline: 'none',
+};
+
+export const markerStyle = {
+ default: {fill: '#00FFAD'},
+ hover: {fill: '#00FFAD'},
+ pressed: {fill: '#00FFAD'},
+};
diff --git a/src/v2/utils/calcChanges.js b/src/v2/utils/calcChanges.js
new file mode 100644
index 00000000..9c942bb2
--- /dev/null
+++ b/src/v2/utils/calcChanges.js
@@ -0,0 +1,8 @@
+// @flow
+
+export default (oldValue: string | number, newValue: string | number) => {
+ if (!oldValue || !newValue) {
+ return 0;
+ }
+ return ((+newValue * 100) / (+oldValue || 1) - 100).toFixed(2);
+};
diff --git a/src/v2/utils/parseMessage.js b/src/v2/utils/parseMessage.js
new file mode 100644
index 00000000..fca067ea
--- /dev/null
+++ b/src/v2/utils/parseMessage.js
@@ -0,0 +1,56 @@
+import {find, compose, split, map} from 'lodash/fp';
+
+export function parseTransaction(message) {
+ const [h, l, s, dt, entry_id, id, inst] = split('#')(message);
+
+ const instructions = compose(
+ map(i => {
+ const [program_id, keys, data] = split('@')(i);
+
+ return {
+ program_id,
+ keys: split(',')(keys),
+ data,
+ };
+ }),
+ split('|'),
+ )(inst);
+
+ return {
+ t: 'txn',
+ h: parseInt(h),
+ l,
+ s: parseInt(s),
+ dt,
+ entry_id,
+ id,
+ instructions,
+ };
+}
+
+export function parseBlock(message) {
+ const [h, l, s, dt, id] = split('#')(message);
+
+ return {
+ t: 'blk',
+ h,
+ l,
+ s: parseInt(s),
+ dt,
+ id,
+ };
+}
+
+export function parseClusterInfo(data) {
+ const {voting, cluster: gossip, supply, feeCalculator} = JSON.parse(data);
+ const nodes = map(g => ({
+ ...g,
+ voteAccount: find({nodePubkey: g.pubKey}, voting),
+ }))(gossip);
+
+ return {
+ nodes,
+ supply,
+ feeCalculator,
+ };
+}
diff --git a/yarn.lock b/yarn.lock
index 60a67a0e..429375db 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -49,17 +49,6 @@
source-map "^0.5.0"
trim-right "^1.0.1"
-"@babel/generator@^7.4.4":
- version "7.4.4"
- resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.4.4.tgz#174a215eb843fc392c7edcaabeaa873de6e8f041"
- integrity sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==
- dependencies:
- "@babel/types" "^7.4.4"
- jsesc "^2.5.1"
- lodash "^4.17.11"
- source-map "^0.5.0"
- trim-right "^1.0.1"
-
"@babel/helper-annotate-as-pure@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32"
@@ -264,16 +253,6 @@
"@babel/traverse" "^7.4.0"
"@babel/types" "^7.4.0"
-"@babel/helper-replace-supers@^7.4.4":
- version "7.4.4"
- resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz#aee41783ebe4f2d3ab3ae775e1cc6f1a90cefa27"
- integrity sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg==
- dependencies:
- "@babel/helper-member-expression-to-functions" "^7.0.0"
- "@babel/helper-optimise-call-expression" "^7.0.0"
- "@babel/traverse" "^7.4.4"
- "@babel/types" "^7.4.4"
-
"@babel/helper-simple-access@^7.1.0":
version "7.1.0"
resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz#65eeb954c8c245beaa4e859da6188f39d71e585c"
@@ -296,13 +275,6 @@
dependencies:
"@babel/types" "^7.4.0"
-"@babel/helper-split-export-declaration@^7.4.4":
- version "7.4.4"
- resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677"
- integrity sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==
- dependencies:
- "@babel/types" "^7.4.4"
-
"@babel/helper-wrap-function@^7.1.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa"
@@ -336,11 +308,6 @@
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.4.3.tgz#eb3ac80f64aa101c907d4ce5406360fe75b7895b"
integrity sha512-gxpEUhTS1sGA63EGQGuA+WESPR/6tz6ng7tSHFCmaTJK/cGK8y37cBTspX+U2xCAue2IQVvF6Z0oigmjwD8YGQ==
-"@babel/parser@^7.4.5":
- version "7.4.5"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.4.5.tgz#04af8d5d5a2b044a2a1bffacc1e5e6673544e872"
- integrity sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==
-
"@babel/plugin-proposal-async-generator-functions@^7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e"
@@ -358,14 +325,6 @@
"@babel/helper-create-class-features-plugin" "^7.4.0"
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-proposal-class-properties@^7.5.0":
- version "7.5.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.5.0.tgz#5bc6a0537d286fcb4fd4e89975adbca334987007"
- integrity sha512-9L/JfPCT+kShiiTTzcnBJ8cOwdKVmlC1RcCf9F0F9tERVrM4iWtWnXtjWCRqNm2la2BxO1MPArWNsU9zsSJWSQ==
- dependencies:
- "@babel/helper-create-class-features-plugin" "^7.5.0"
- "@babel/helper-plugin-utils" "^7.0.0"
-
"@babel/plugin-proposal-decorators@7.4.0":
version "7.4.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.4.0.tgz#8e1bfd83efa54a5f662033afcc2b8e701f4bb3a9"
@@ -375,15 +334,6 @@
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-decorators" "^7.2.0"
-"@babel/plugin-proposal-decorators@^7.4.4":
- version "7.4.4"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.4.4.tgz#de9b2a1a8ab0196f378e2a82f10b6e2a36f21cc0"
- integrity sha512-z7MpQz3XC/iQJWXH9y+MaWcLPNSMY9RQSthrLzak8R8hCj0fuyNk+Dzi9kfNe/JxxlWQ2g7wkABbgWjW36MTcw==
- dependencies:
- "@babel/helper-create-class-features-plugin" "^7.4.4"
- "@babel/helper-plugin-utils" "^7.0.0"
- "@babel/plugin-syntax-decorators" "^7.2.0"
-
"@babel/plugin-proposal-json-strings@^7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz#568ecc446c6148ae6b267f02551130891e29f317"
@@ -1113,21 +1063,6 @@
globals "^11.1.0"
lodash "^4.17.11"
-"@babel/traverse@^7.4.4":
- version "7.4.5"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.4.5.tgz#4e92d1728fd2f1897dafdd321efbff92156c3216"
- integrity sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==
- dependencies:
- "@babel/code-frame" "^7.0.0"
- "@babel/generator" "^7.4.4"
- "@babel/helper-function-name" "^7.1.0"
- "@babel/helper-split-export-declaration" "^7.4.4"
- "@babel/parser" "^7.4.5"
- "@babel/types" "^7.4.4"
- debug "^4.1.0"
- globals "^11.1.0"
- lodash "^4.17.11"
-
"@babel/types@^7.0.0", "@babel/types@^7.1.6", "@babel/types@^7.2.0", "@babel/types@^7.2.2", "@babel/types@^7.3.0", "@babel/types@^7.4.0":
version "7.4.0"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.4.0.tgz#670724f77d24cce6cc7d8cf64599d511d164894c"
@@ -1137,7 +1072,7 @@
lodash "^4.17.11"
to-fast-properties "^2.0.0"
-"@babel/types@^7.0.0-beta.49", "@babel/types@^7.4.4":
+"@babel/types@^7.0.0-beta.49":
version "7.4.4"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.4.4.tgz#8db9e9a629bb7c29370009b4b779ed93fe57d5f0"
integrity sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==
@@ -1603,6 +1538,113 @@
call-me-maybe "^1.0.1"
glob-to-regexp "^0.3.0"
+"@nivo/annotations@0.59.1":
+ version "0.59.1"
+ resolved "https://registry.yarnpkg.com/@nivo/annotations/-/annotations-0.59.1.tgz#25ac2d9138361820f40ad3bf9ff32ada6f02f72d"
+ integrity sha512-syTnvg9ZM4t6UYup6/t+cr1Xc+g6jwuq2GiPemlhe2tTmKvA2vTTeTRskXKgkU1R7B+1Su8BfIeU0F8IXfP1/w==
+ dependencies:
+ "@nivo/colors" "0.59.0"
+ "@nivo/core" "0.59.1"
+ lodash "^4.17.11"
+ react-motion "^0.5.2"
+
+"@nivo/axes@0.59.1":
+ version "0.59.1"
+ resolved "https://registry.yarnpkg.com/@nivo/axes/-/axes-0.59.1.tgz#04989ef4b8f35a29191f9993b3432e0779df4469"
+ integrity sha512-e4yhIJiUmI1aE4SvE9xudtf0GNx9kKIa2fGymHwgwhOAd8G733SyxlPHXrS7/xbTyB8QkMsB6kG+17BxArv12g==
+ dependencies:
+ "@nivo/core" "0.59.1"
+ d3-format "^1.3.2"
+ d3-time "^1.0.11"
+ d3-time-format "^2.1.3"
+ lodash "^4.17.11"
+ react-motion "^0.5.2"
+
+"@nivo/colors@0.59.0":
+ version "0.59.0"
+ resolved "https://registry.yarnpkg.com/@nivo/colors/-/colors-0.59.0.tgz#326f7941de7387099732143063f657a461bd1dfb"
+ integrity sha512-byhooRzg6mLlwDc5Nbe2te8OabAvBG8unlK7AsmavffcVk57qBpyT+ovSCSarZeKXfG2EvRTzCU3Xzt+rDl8ZA==
+ dependencies:
+ d3-color "^1.2.3"
+ d3-scale "^3.0.0"
+ d3-scale-chromatic "^1.3.3"
+ lodash.get "^4.4.2"
+ lodash.isplainobject "^4.0.6"
+ react-motion "^0.5.2"
+
+"@nivo/core@0.59.1":
+ version "0.59.1"
+ resolved "https://registry.yarnpkg.com/@nivo/core/-/core-0.59.1.tgz#2fd19d8963a2279a40746ff8f18ea9ad286bb447"
+ integrity sha512-eh/A6KKfsp2tGzZp5ofD8APueLfq7rASk5OIQawqpwgWEWJ3bOFfAvxN67U0mnAtJlbOhZuZiXoivFYXJ8nReQ==
+ dependencies:
+ "@nivo/tooltip" "0.59.1"
+ d3-color "^1.2.3"
+ d3-format "^1.3.2"
+ d3-hierarchy "^1.1.8"
+ d3-interpolate "^1.3.2"
+ d3-scale "^3.0.0"
+ d3-scale-chromatic "^1.3.3"
+ d3-shape "^1.3.5"
+ d3-time-format "^2.1.3"
+ lodash "^4.17.11"
+ react-measure "^2.2.4"
+ react-motion "^0.5.2"
+ recompose "^0.30.0"
+
+"@nivo/legends@0.59.1":
+ version "0.59.1"
+ resolved "https://registry.yarnpkg.com/@nivo/legends/-/legends-0.59.1.tgz#9ae44bc09e3f11be4017c1a37e55b7218663bad8"
+ integrity sha512-VTK5eco/cCTw47dEzcARGzbyXV5I6r64KN0HjpljonqxslyEa4My5lHvCE+eeNuEPYPPsk0NkO/ycNpdO6vi/A==
+ dependencies:
+ "@nivo/core" "0.59.1"
+ lodash "^4.17.11"
+ recompose "^0.30.0"
+
+"@nivo/line@^0.59.1":
+ version "0.59.1"
+ resolved "https://registry.yarnpkg.com/@nivo/line/-/line-0.59.1.tgz#b3ebdb6a6a5a1c276e4ce34422ee5a44c8ddf5ee"
+ integrity sha512-AD8c/5oqO7I2tTeDeg1BCGICLnnYXw1k7g0OGJwxMthxBWtkvXMHMM132/VyzBQnB9uf5Mp9vernf3ZI0QE4Rg==
+ dependencies:
+ "@nivo/annotations" "0.59.1"
+ "@nivo/axes" "0.59.1"
+ "@nivo/colors" "0.59.0"
+ "@nivo/core" "0.59.1"
+ "@nivo/legends" "0.59.1"
+ "@nivo/scales" "0.59.1"
+ "@nivo/tooltip" "0.59.1"
+ "@nivo/voronoi" "0.59.1"
+ d3-shape "^1.3.5"
+ lodash "^4.17.11"
+ react-motion "^0.5.2"
+
+"@nivo/scales@0.59.1":
+ version "0.59.1"
+ resolved "https://registry.yarnpkg.com/@nivo/scales/-/scales-0.59.1.tgz#20092ca1f0f509961723ad3de2e737f4a08a2e33"
+ integrity sha512-hOl4xgxDQhRos85YQTJCXHdLdow6FR5dhe/uA3WbOcnkaCkLyE+0g9RHPxmkWapB8QSjkfM0BJSltdfSSvUpog==
+ dependencies:
+ d3-scale "^3.0.0"
+ d3-time-format "^2.1.3"
+ lodash "^4.17.11"
+
+"@nivo/tooltip@0.59.1":
+ version "0.59.1"
+ resolved "https://registry.yarnpkg.com/@nivo/tooltip/-/tooltip-0.59.1.tgz#82e981d6af397b1f18a8a2906c8fd60da0234881"
+ integrity sha512-vpWxZxTVRDy4deCDXwTk3N65GZfSVba9MxpYSJIWrI+Uln1Po66btdQqSeHhS5NCdr15ebjksWqUagtxWU42iw==
+ dependencies:
+ "@nivo/core" "0.59.1"
+ react-measure "^2.2.4"
+ react-motion "^0.5.2"
+
+"@nivo/voronoi@0.59.1":
+ version "0.59.1"
+ resolved "https://registry.yarnpkg.com/@nivo/voronoi/-/voronoi-0.59.1.tgz#08c6446ff5d9526214a46d16fe2b5f69810657e0"
+ integrity sha512-3E2sZps+iwJzvx4Ct+FScnP3N7Adi5r0yHjQQ9PeHtJVZ44QP/EzEuqp6jWn8WsqV913iFtIR2/o40PdEmLfxA==
+ dependencies:
+ "@nivo/core" "0.59.1"
+ d3-delaunay "^4.1.5"
+ d3-scale "^3.0.0"
+ recompose "^0.30.0"
+
"@nodelib/fs.stat@^1.1.2":
version "1.1.3"
resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
@@ -2597,7 +2639,7 @@ arrify@^1.0.1:
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=
-asap@^2.0.0, asap@~2.0.6:
+asap@^2.0.0, asap@~2.0.3, asap@~2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
@@ -2977,6 +3019,13 @@ babel-plugin-check-es2015-constants@^6.22.0:
dependencies:
babel-runtime "^6.22.0"
+babel-plugin-date-fns@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-date-fns/-/babel-plugin-date-fns-0.2.1.tgz#17b6e4666a05411857ac04af4318ff5fb72895f2"
+ integrity sha512-XdcYohZbmetNsEHG32QV+uC17J3LKfE5O5/47N+Ee9zR1xdqXPRm/Am1VbGidva7dFpRzXmdk4TYofS9Qq+1Tw==
+ dependencies:
+ lodash.snakecase "^4.1.1"
+
babel-plugin-dynamic-import-node@2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.2.0.tgz#c0adfb07d95f4a4495e9aaac6ec386c4d7c2524e"
@@ -4073,6 +4122,11 @@ chalk@^1.0.0, chalk@^1.1.3:
strip-ansi "^3.0.0"
supports-color "^2.0.0"
+change-emitter@^0.1.2:
+ version "0.1.6"
+ resolved "https://registry.yarnpkg.com/change-emitter/-/change-emitter-0.1.6.tgz#e8b2fe3d7f1ab7d69a32199aff91ea6931409515"
+ integrity sha1-6LL+PX8at9aaMhma/5HqaTFAlRU=
+
chardet@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
@@ -4739,6 +4793,11 @@ core-js@3.0.1:
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.0.1.tgz#1343182634298f7f38622f95e73f54e48ddf4738"
integrity sha512-sco40rF+2KlE0ROMvydjkrVMMG1vYilP2ALoRXcYR4obqbYIuV3Bg+51GEDW+HF8n7NRA+iaA4qD0nD9lo9mew==
+core-js@^1.0.0:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
+ integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=
+
core-js@^2.4.0, core-js@^2.5.0:
version "2.6.5"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.5.tgz#44bc8d249e7fb2ff5d00e0341a7ffb94fbf67895"
@@ -5126,6 +5185,28 @@ d3-array@1:
resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f"
integrity sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==
+"d3-array@^1.2.0 || 2":
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-2.2.0.tgz#a9e966b8f8d78f0888d98db1fb840fc8da8ac5c7"
+ integrity sha512-eE0QmSh6xToqM3sxHiJYg/QFdNn52ZEgmFE8A8abU8GsHvsIOolqH8B70/8+VGAKm5MlwaExhqR3DLIjOJMLPA==
+
+d3-color@1, d3-color@^1.2.3:
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-1.2.8.tgz#4eaf9b60ef188c893fcf8b28f3546aafebfbd9f4"
+ integrity sha512-yeANXzP37PHk0DbSTMNPhnJD+Nn4G//O5E825bR6fAfHH43hobSBpgB9G9oWVl9+XgUaQ4yCnsX1H+l8DoaL9A==
+
+d3-delaunay@^4.1.5:
+ version "4.1.5"
+ resolved "https://registry.yarnpkg.com/d3-delaunay/-/d3-delaunay-4.1.5.tgz#4318c6d28b22988d88d11650eda440318afe419a"
+ integrity sha512-rBKVohmXT9+BrDicH8umAVUwtkfLIydVlWnpIEDUZ4l2e1vXCaKbypByF8tkN8TUUKnzJY0s8ldQEroeBRMO9Q==
+ dependencies:
+ delaunator "^2.0.0"
+
+d3-format@1, d3-format@^1.3.2:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.3.2.tgz#6a96b5e31bcb98122a30863f7d92365c00603562"
+ integrity sha512-Z18Dprj96ExragQ0DeGi+SYPQ7pPfRMtUXtsg/ChVIKNBCzjO8XYJvRTC1usblx52lqge56V5ect+frYTQc8WQ==
+
d3-geo-projection@1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/d3-geo-projection/-/d3-geo-projection-1.2.2.tgz#ef0e6cdcfa0df236d0e23f2ca7750462ca331f72"
@@ -5149,6 +5230,61 @@ d3-geo@^1.1.0:
dependencies:
d3-array "1"
+d3-hierarchy@^1.1.8:
+ version "1.1.8"
+ resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-1.1.8.tgz#7a6317bd3ed24e324641b6f1e76e978836b008cc"
+ integrity sha512-L+GHMSZNwTpiq4rt9GEsNcpLa4M96lXMR8M/nMG9p5hBE0jy6C+3hWtyZMenPQdwla249iJy7Nx0uKt3n+u9+w==
+
+d3-interpolate@1, d3-interpolate@^1.3.2:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-1.3.2.tgz#417d3ebdeb4bc4efcc8fd4361c55e4040211fd68"
+ integrity sha512-NlNKGopqaz9qM1PXh9gBF1KSCVh+jSFErrSlD/4hybwoNX/gt1d8CDbDW+3i+5UOHhjC6s6nMvRxcuoMVNgL2w==
+ dependencies:
+ d3-color "1"
+
+d3-path@1:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.7.tgz#8de7cd693a75ac0b5480d3abaccd94793e58aae8"
+ integrity sha512-q0cW1RpvA5c5ma2rch62mX8AYaiLX0+bdaSM2wxSU9tXjU4DNvkx9qiUvjkuWCj3p22UO/hlPivujqMiR9PDzA==
+
+d3-scale-chromatic@^1.3.3:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-1.3.3.tgz#dad4366f0edcb288f490128979c3c793583ed3c0"
+ integrity sha512-BWTipif1CimXcYfT02LKjAyItX5gKiwxuPRgr4xM58JwlLocWbjPLI7aMEjkcoOQXMkYsmNsvv3d2yl/OKuHHw==
+ dependencies:
+ d3-color "1"
+ d3-interpolate "1"
+
+d3-scale@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-3.0.0.tgz#ddede1278ac3ea2bf3666de6ca625e20bed9b6c9"
+ integrity sha512-ktic5HBFlAZj2CN8CCl/p/JyY8bMQluN7+fA6ICE6yyoMOnSQAZ1Bb8/5LcNpNKMBMJge+5Vv4pWJhARYlQYFw==
+ dependencies:
+ d3-array "^1.2.0 || 2"
+ d3-format "1"
+ d3-interpolate "1"
+ d3-time "1"
+ d3-time-format "2"
+
+d3-shape@^1.3.5:
+ version "1.3.5"
+ resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.3.5.tgz#e81aea5940f59f0a79cfccac012232a8987c6033"
+ integrity sha512-VKazVR3phgD+MUCldapHD7P9kcrvPcexeX/PkMJmkUov4JM8IxsSg1DvbYoYich9AtdTsa5nNk2++ImPiDiSxg==
+ dependencies:
+ d3-path "1"
+
+d3-time-format@2, d3-time-format@^2.1.3:
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-2.1.3.tgz#ae06f8e0126a9d60d6364eac5b1533ae1bac826b"
+ integrity sha512-6k0a2rZryzGm5Ihx+aFMuO1GgelgIz+7HhB4PH4OEndD5q2zGn1mDfRdNrulspOfR6JXkb2sThhDK41CSK85QA==
+ dependencies:
+ d3-time "1"
+
+d3-time@1, d3-time@^1.0.11:
+ version "1.0.11"
+ resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.0.11.tgz#1d831a3e25cd189eb256c17770a666368762bbce"
+ integrity sha512-Z3wpvhPLW4vEScGeIMUckDW7+3hWKOQfAWg/U7PlWBnQmeKQ00gCUsTtWSYulrKNA7ta8hJ+xXc6MHrMuITwEw==
+
damerau-levenshtein@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz#03191c432cb6eea168bb77f3a55ffdccb8978514"
@@ -5177,7 +5313,7 @@ data-urls@^1.0.0, data-urls@^1.1.0:
whatwg-mimetype "^2.2.0"
whatwg-url "^7.0.0"
-date-fns@^1.27.2:
+date-fns@^1.27.2, date-fns@^1.30.1:
version "1.30.1"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c"
integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==
@@ -5370,6 +5506,11 @@ del@^4.1.1:
pify "^4.0.1"
rimraf "^2.6.3"
+delaunator@^2.0.0:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-2.0.5.tgz#c2a9ba2cf3d5aaab8fa0aa3ae82426d3fc0aeaf5"
+ integrity sha512-GSYmkITO56erpQzv5Pw+8Vg769kurM16IVUq/AcMb5ZCJCtV7Z2agx9lJ7EbbLno8L099iH2d+hvAK34ZnsvIQ==
+
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
@@ -6457,6 +6598,19 @@ fb-watchman@^2.0.0:
dependencies:
bser "^2.0.0"
+fbjs@^0.8.1:
+ version "0.8.17"
+ resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd"
+ integrity sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=
+ dependencies:
+ core-js "^1.0.0"
+ isomorphic-fetch "^2.1.1"
+ loose-envify "^1.0.0"
+ object-assign "^4.1.0"
+ promise "^7.1.1"
+ setimmediate "^1.0.5"
+ ua-parser-js "^0.7.18"
+
fd-slicer@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
@@ -6929,6 +7083,11 @@ get-caller-file@^2.0.1:
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
+get-node-dimensions@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/get-node-dimensions/-/get-node-dimensions-1.2.1.tgz#fb7b4bb57060fb4247dd51c9d690dfbec56b0823"
+ integrity sha512-2MSPMu7S1iOTL+BOa6K1S62hB2zUAYNF/lV0gSVlOaacd087lc6nR1H1r0e3B1CerTo+RceOmi1iJW+vp21xcQ==
+
get-own-enumerable-property-symbols@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz#b877b49a5c16aefac3655f2ed2ea5b684df8d203"
@@ -7394,6 +7553,11 @@ hoek@6.x.x:
resolved "https://registry.yarnpkg.com/hoek/-/hoek-6.1.3.tgz#73b7d33952e01fe27a38b0457294b79dd8da242c"
integrity sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==
+hoist-non-react-statics@^2.3.1:
+ version "2.5.5"
+ resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47"
+ integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==
+
hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.2.1, hoist-non-react-statics@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz#b09178f0122184fb95acf525daaecb4d8f45958b"
@@ -8257,7 +8421,7 @@ is-root@2.0.0:
resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.0.0.tgz#838d1e82318144e5a6f77819d90207645acc7019"
integrity sha512-F/pJIk8QD6OX5DNhRB7hWamLsUilmkDGho48KbgZ6xg/lmAZXHxzXQ91jzB3yRSw5kdQGGGc4yz8HYhTYIMWPg==
-is-stream@^1.0.0, is-stream@^1.1.0:
+is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
@@ -8347,6 +8511,14 @@ isobject@^4.0.0:
resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0"
integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==
+isomorphic-fetch@^2.1.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
+ integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=
+ dependencies:
+ node-fetch "^1.0.1"
+ whatwg-fetch ">=0.10.0"
+
isstream@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
@@ -9659,6 +9831,11 @@ lodash.set@^4.3.2:
resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23"
integrity sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=
+lodash.snakecase@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d"
+ integrity sha1-OdcUo1NXFHg3rv1ktdy7Fr7Nj40=
+
lodash.some@^4.4.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d"
@@ -10460,6 +10637,14 @@ node-fetch-npm@^2.0.2:
json-parse-better-errors "^1.0.0"
safe-buffer "^5.1.1"
+node-fetch@^1.0.1:
+ version "1.7.3"
+ resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
+ integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==
+ dependencies:
+ encoding "^0.1.11"
+ is-stream "^1.0.1"
+
node-fetch@^2.1.1:
version "2.6.0"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
@@ -11569,6 +11754,11 @@ pend@~1.2.0:
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA=
+performance-now@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
+ integrity sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=
+
performance-now@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
@@ -12440,6 +12630,13 @@ promise@8.0.2:
dependencies:
asap "~2.0.6"
+promise@^7.1.1:
+ version "7.3.1"
+ resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
+ integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==
+ dependencies:
+ asap "~2.0.3"
+
prompts@^2.0.1:
version "2.0.4"
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.0.4.tgz#179f9d4db3128b9933aa35f93a800d8fce76a682"
@@ -12633,7 +12830,7 @@ qw@~1.0.1:
resolved "https://registry.yarnpkg.com/qw/-/qw-1.0.1.tgz#efbfdc740f9ad054304426acb183412cc8b996d4"
integrity sha1-77/cdA+a0FQwRCassYNBLMi5ltQ=
-raf@3.4.1:
+raf@3.4.1, raf@^3.1.0:
version "3.4.1"
resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==
@@ -12815,11 +13012,30 @@ react-is@^16.8.0, react-is@^16.8.4:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16"
integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==
-react-lifecycles-compat@^3.0.4:
+react-lifecycles-compat@^3.0.2, react-lifecycles-compat@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
+react-measure@^2.2.4:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/react-measure/-/react-measure-2.3.0.tgz#75835d39abec9ae13517f35a819c160997a7a44e"
+ integrity sha512-dwAvmiOeblj5Dvpnk8Jm7Q8B4THF/f1l1HtKVi0XDecsG6LXwGvzV5R1H32kq3TW6RW64OAf5aoQxpIgLa4z8A==
+ dependencies:
+ "@babel/runtime" "^7.2.0"
+ get-node-dimensions "^1.2.1"
+ prop-types "^15.6.2"
+ resize-observer-polyfill "^1.5.0"
+
+react-motion@^0.5.2:
+ version "0.5.2"
+ resolved "https://registry.yarnpkg.com/react-motion/-/react-motion-0.5.2.tgz#0dd3a69e411316567927917c6626551ba0607316"
+ integrity sha512-9q3YAvHoUiWlP3cK0v+w1N5Z23HXMj4IF4YuvjvWegWqNPfLXsOBE/V7UvQGpXxHFKRQQcNcVQE31g9SB/6qgQ==
+ dependencies:
+ performance-now "^0.2.0"
+ prop-types "^15.5.8"
+ raf "^3.1.0"
+
react-router-dom@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.0.1.tgz#ee66f4a5d18b6089c361958e443489d6bab714be"
@@ -13127,6 +13343,18 @@ realpath-native@^1.1.0:
dependencies:
util.promisify "^1.0.0"
+recompose@^0.30.0:
+ version "0.30.0"
+ resolved "https://registry.yarnpkg.com/recompose/-/recompose-0.30.0.tgz#82773641b3927e8c7d24a0d87d65aeeba18aabd0"
+ integrity sha512-ZTrzzUDa9AqUIhRk4KmVFihH0rapdCSMFXjhHbNrjAWxBuUD/guYlyysMnuHjlZC/KRiOKRtB4jf96yYSkKE8w==
+ dependencies:
+ "@babel/runtime" "^7.0.0"
+ change-emitter "^0.1.2"
+ fbjs "^0.8.1"
+ hoist-non-react-statics "^2.3.1"
+ react-lifecycles-compat "^3.0.2"
+ symbol-observable "^1.0.4"
+
recursive-readdir@2.2.2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f"
@@ -13455,6 +13683,11 @@ requires-port@^1.0.0:
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
+resize-observer-polyfill@^1.5.0:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
+ integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
+
resolve-cwd@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
@@ -13883,7 +14116,7 @@ set-value@^2.0.0:
is-plain-object "^2.0.3"
split-string "^3.0.1"
-setimmediate@^1.0.4, setimmediate@~1.0.4:
+setimmediate@^1.0.4, setimmediate@^1.0.5, setimmediate@~1.0.4:
version "1.0.5"
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=
@@ -14624,7 +14857,7 @@ svgo@^1.0.0, svgo@^1.1.1:
unquote "~1.1.1"
util.promisify "~1.0.0"
-symbol-observable@^1.1.0:
+symbol-observable@^1.0.4, symbol-observable@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
@@ -15015,6 +15248,11 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
+ua-parser-js@^0.7.18:
+ version "0.7.20"
+ resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.20.tgz#7527178b82f6a62a0f243d1f94fd30e3e3c21098"
+ integrity sha512-8OaIKfzL5cpx8eCMAhhvTlft8GYF8b2eQr6JkCyVdrgjcytyOmPCXrqXFcUnhonRpLlh5yxEZVohm6mzaowUOw==
+
uglify-js@3.4.x, uglify-js@^3.1.4:
version "3.4.9"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3"
@@ -15595,7 +15833,7 @@ whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3, whatwg-encoding@^1.0.5:
dependencies:
iconv-lite "0.4.24"
-whatwg-fetch@3.0.0:
+whatwg-fetch@3.0.0, whatwg-fetch@>=0.10.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb"
integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==