feat: connections inspection

This commit is contained in:
Haishan 2019-11-08 00:40:48 +08:00
parent 1307934464
commit 6754620d7a
14 changed files with 393 additions and 197 deletions

View file

@ -34,12 +34,13 @@
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.7.1",
"@hot-loader/react-dom": "^16.9.0",
"@hot-loader/react-dom": "16.10.2",
"@hsjs/react-cache": "0.0.0-alpha.aa94237",
"@sentry/browser": "^5.7.1",
"chart.js": "^2.9.2",
"classnames": "^2.2.6",
"core-js": "^3.3.6",
"date-fns": "^2.7.0",
"history": "^4.7.2",
"invariant": "^2.2.4",
"lodash-es": "^4.17.14",
@ -48,8 +49,10 @@
"prop-types": "^15.5.10",
"react": "^0.0.0-experimental-f6b8d31a7",
"react-dom": "^0.0.0-experimental-f6b8d31a7",
"react-feather": "^2.0.3",
"react-modal": "^3.11.1",
"react-router-dom": "^5.1.2",
"react-table": "^7.0.0-beta.12",
"react-window": "^1.8.5",
"redux": "^4.0.4",
"redux-logger": "^3.0.6",

51
src/api/connections.js Normal file
View file

@ -0,0 +1,51 @@
const endpoint = '/connections';
let fetched = false;
let subscribers = [];
function appendData(s) {
let o;
try {
o = JSON.parse(s);
} catch (err) {
// eslint-disable-next-line no-console
console.log('JSON.parse error', JSON.parse(s));
}
subscribers.forEach(f => f(o));
}
function getWsUrl(apiConfig) {
const { hostname, port, secret } = apiConfig;
let qs = '';
if (typeof secret === 'string' && secret !== '') {
qs += '?token=' + secret;
}
return `ws://${hostname}:${port}${endpoint}${qs}`;
}
let wsState;
function fetchData(apiConfig, listener) {
if (fetched || wsState === 1) {
if (listener) return subscribe(listener);
}
wsState = 1;
const url = getWsUrl(apiConfig);
const ws = new WebSocket(url);
ws.addEventListener('error', function(_ev) {
wsState = 3;
});
ws.addEventListener('message', function(event) {
appendData(event.data);
});
if (listener) return subscribe(listener);
}
function subscribe(listener) {
subscribers.push(listener);
return function unsubscribe() {
const idx = subscribers.indexOf(listener);
subscribers.splice(idx, 1);
};
}
export { fetchData };

View file

@ -0,0 +1,99 @@
import React from 'react';
import { ArrowUp, ArrowDown } from 'react-feather';
import prettyBytes from '../misc/pretty-bytes';
import { formatDistance } from 'date-fns';
import cx from 'classnames';
import { useTable, useSortBy } from 'react-table';
import s from './ConnectionTable.module.css';
const columns = [
{ Header: 'Host', accessor: 'host' },
{ Header: 'Download', accessor: 'download' },
{ Header: 'Upload', accessor: 'upload' },
{ Header: 'Network', accessor: 'network' },
{ Header: 'Type', accessor: 'type' },
{ Header: 'Chains', accessor: 'chains' },
{ Header: 'Rule', accessor: 'rule' },
{ Header: 'Time', accessor: 'start' },
{ Header: 'Source IP', accessor: 'sourceIP' },
{ Header: 'Source Port', accessor: 'sourcePort' },
{ Header: 'Designation IP', accessor: 'destinationIP' },
{ Header: 'Designation Port', accessor: 'destinationPort' }
];
function renderCell(cell, now) {
switch (cell.column.id) {
case 'start':
return formatDistance(-cell.value, now);
case 'download':
case 'upload':
return prettyBytes(cell.value);
default:
return cell.value;
}
}
function Table({ data }) {
const now = new Date();
const {
getTableProps,
// getTableBodyProps,
headerGroups,
rows,
prepareRow
} = useTable(
{
columns,
data
},
useSortBy
);
return (
<div {...getTableProps()}>
<div className={s.thead}>
{headerGroups.map(headerGroup => (
<div {...headerGroup.getHeaderGroupProps()} className={s.tr}>
{headerGroup.headers.map(column => (
<div
{...column.getHeaderProps(column.getSortByToggleProps())}
className={s.th}
>
<span>{column.render('Header')}</span>
<span>
{column.isSorted ? (
column.isSortedDesc ? (
<ArrowDown size={16} />
) : (
<ArrowUp size={16} />
)
) : null}
</span>
</div>
))}
{rows.map((row, i) => {
prepareRow(row);
return row.cells.map((cell, j) => {
return (
<div
{...cell.getCellProps()}
className={cx(
s.td,
i % 2 === 0 ? s.odd : false,
j === 1 || j === 2 ? s.du : false
)}
>
{renderCell(cell, now)}
</div>
);
});
})}
</div>
))}
</div>
</div>
);
}
export default Table;

View file

@ -0,0 +1,38 @@
.thead .tr {
display: grid;
grid-template-columns: repeat(12, max-content);
}
.th {
padding: 8px 0 14px 10px;
height: 50px;
background: var(--color-background);
position: sticky;
top: 0;
display: flex;
align-items: center;
justify-content: space-between;
}
.th span:last-child {
margin-left: 10px;
width: 16px;
height: 16px;
}
.td {
padding: 8px 10px;
font-size: 0.9em;
font-family: var(--font-normal);
}
.td.odd {
background: var(--color-row-odd);
}
/* download upload td cells */
.du {
text-align: right;
}

View file

@ -0,0 +1,55 @@
import React from 'react';
import ContentHeader from 'c/ContentHeader';
import ConnectionTable from 'c/ConnectionTable';
import useRemainingViewPortHeight from '../hooks/useRemainingViewPortHeight';
import { useStoreState } from 'm/store';
import { getClashAPIConfig } from 'd/app';
import * as connAPI from '../api/connections';
const { useEffect, useState } = React;
const paddingBottom = 30;
function formatConnectionDataItem(i) {
const { id, metadata, upload, download, start, chains, rule } = i;
// const started = formatDistance(new Date(start), now);
return {
id,
upload,
download,
start: 0 - new Date(start),
chains: chains.reverse().join(' / '),
rule,
...metadata
};
}
function Conn() {
const [refContainer, containerHeight] = useRemainingViewPortHeight();
const config = useStoreState(getClashAPIConfig);
const [conns, setConns] = useState([]);
useEffect(() => {
function read({ connections }) {
const x = connections.map(c => formatConnectionDataItem(c));
setConns(x);
}
return connAPI.fetchData(config, read);
}, [config]);
return (
<div>
<ContentHeader title="Connections" />
<div
ref={refContainer}
style={{ padding: 30, paddingBottom, paddingTop: 0 }}
>
<div
style={{ height: containerHeight - paddingBottom, overflow: 'auto' }}
>
<ConnectionTable data={conns} />
</div>
</div>
</div>
);
}
export default Conn;

View file

@ -61,6 +61,9 @@
:root {
--font-mono: 'Roboto Mono', Menlo, monospace;
--font-normal: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica,
Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol,
'PingFang SC', 'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
--color-focus-blue: #1a73e8;
}
@ -88,6 +91,7 @@ body.dark {
--color-btn-bg: #232323;
--color-btn-fg: #bebebe;
--color-bg-proxy-selected: #303030;
--color-row-odd: #282828;
}
body.light {
@ -104,4 +108,5 @@ body.light {
--color-btn-bg: #f4f4f4;
--color-btn-fg: #101010;
--color-bg-proxy-selected: #cfcfcf;
--color-row-odd: #f5f5f5;
}

View file

@ -8,6 +8,7 @@ import SideBar from 'c/SideBar';
import Home from 'c/Home';
import Logs from 'c/Logs';
import Config from 'c/Config';
import Connections from 'c/Connections';
import APIDiscovery from 'c/APIDiscovery';
import { store } from '../store/configureStore';
import './Root.css';
@ -45,6 +46,7 @@ const Root = () => (
<div className={s0.content}>
<Suspense fallback={<Loading2 />}>
<Route exact path="/" render={() => <Home />} />
<Route exact path="/connections" component={Connections} />
<Route exact path="/overview" render={() => <Home />} />
<Route exact path="/configs" component={Config} />
<Route exact path="/logs" component={Logs} />

View file

@ -2,6 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import { Link } from 'react-router-dom';
import { Command, Activity, Globe, Link2, Settings, File } from 'react-feather';
import { useActions } from 'm/store';
import { switchTheme } from 'd/app';
@ -11,20 +12,16 @@ import Icon from 'c/Icon';
import moon from 's/moon.svg';
import SvgYacd from './SvgYacd';
import SvgActivity from './SvgActivity';
import SvgGlobe from './SvgGlobe';
import SvgCommand from './SvgCommand';
import SvgSettings from './SvgSettings';
import SvgFile from './SvgFile';
import s from 'c/SideBar.module.css';
const icons = {
activity: SvgActivity,
globe: SvgGlobe,
command: SvgCommand,
file: SvgFile,
settings: SvgSettings
activity: Activity,
globe: Globe,
command: Command,
file: File,
settings: Settings,
link: Link2
};
const SideBarRow = React.memo(function SideBarRow({
@ -38,7 +35,7 @@ const SideBarRow = React.memo(function SideBarRow({
const className = cx(s.row, isActive ? s.rowActive : null);
return (
<Link to={to} className={className}>
<Comp isActive={isActive} />
<Comp />
<div className={s.label}>{labelText}</div>
</Link>
);
@ -89,6 +86,12 @@ function SideBar({ location }) {
iconId="command"
labelText="Rules"
/>
<SideBarRow
to="/connections"
location={location}
iconId="link"
labelText="Conns"
/>
<SideBarRow
to="/configs"
location={location}

View file

@ -1,24 +0,0 @@
import React from 'react';
function SvgActivity() {
return (
<svg
width="28"
height="28"
viewBox="0 0 28 28"
xmlns="http://www.w3.org/2000/svg"
>
<g
fill="none"
fillRule="evenodd"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
>
<path d="M24 14h-4l-3 9-6-18-3 9H4" stroke="currentColor" />
</g>
</svg>
);
}
export default SvgActivity;

View file

@ -1,25 +0,0 @@
import React from 'react';
export default function SvgCommand() {
return (
<svg
width="28"
height="28"
viewBox="0 0 28 28"
xmlns="http://www.w3.org/2000/svg"
>
<g
fill="none"
fillRule="evenodd"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
>
<path
d="M20 5a3 3 0 0 0-3 3v12a3 3 0 1 0 3-3H8a3 3 0 1 0 3 3V8a3 3 0 1 0-3 3h12a3 3 0 0 0 0-6z"
stroke="currentColor"
/>
</g>
</svg>
);
}

View file

@ -1,25 +0,0 @@
import React from 'react';
export default function SvgFile() {
return (
<svg
width="28"
height="28"
viewBox="0 0 28 28"
xmlns="http://www.w3.org/2000/svg"
>
<g
fill="none"
fillRule="evenodd"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
>
<g stroke="currentColor">
<path d="M16 4H8a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V10l-6-6z" />
<path d="M16 4v6h6M18 15h-8M18 19h-8M12 11h-2" />
</g>
</g>
</svg>
);
}

View file

@ -1,25 +0,0 @@
import React from 'react';
export default function SvgGlobe() {
return (
<svg
width="28"
height="28"
viewBox="0 0 28 28"
xmlns="http://www.w3.org/2000/svg"
>
<g
fill="none"
fillRule="evenodd"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
>
<g transform="translate(4 4)" stroke="currentColor">
<circle cx="10" cy="10" r="10" />
<path d="M0 10h20M10 0a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" />
</g>
</g>
</svg>
);
}

View file

@ -1,25 +0,0 @@
import React from 'react';
export default function SvgSettings() {
return (
<svg
width="28"
height="28"
viewBox="0 0 28 28"
xmlns="http://www.w3.org/2000/svg"
>
<g
fill="none"
fillRule="evenodd"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
>
<g transform="translate(3 3)" stroke="currentColor">
<circle cx="11" cy="11" r="3" />
<path d="M18.4 14a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V20a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 8 18.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H2a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 3.6 8a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H8a1.65 1.65 0 0 0 1-1.51V2a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V8c.26.604.852.997 1.51 1H20a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
</g>
</g>
</svg>
);
}

186
yarn.lock
View file

@ -10,18 +10,18 @@
"@babel/highlight" "^7.0.0"
"@babel/core@^7.7.0":
version "7.7.0"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.0.tgz#461d2948b1a7113088baf999499bcbd39a7faa3b"
integrity sha512-Bb1NjZCaiwTQC/ARL+MwDpgocdnwWDCaugvkGt6cxfBzQa8Whv1JybBoUEiBDKl8Ni3H3c7Fykwk7QChUsHRlg==
version "7.7.2"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.2.tgz#ea5b99693bcfc058116f42fa1dd54da412b29d91"
integrity sha512-eeD7VEZKfhK1KUXGiyPFettgF3m513f8FoBSWiQ1xTvl1RAopLs42Wp9+Ze911I6H0N9lNqJMDgoZT7gHsipeQ==
dependencies:
"@babel/code-frame" "^7.5.5"
"@babel/generator" "^7.7.0"
"@babel/generator" "^7.7.2"
"@babel/helpers" "^7.7.0"
"@babel/parser" "^7.7.0"
"@babel/parser" "^7.7.2"
"@babel/template" "^7.7.0"
"@babel/traverse" "^7.7.0"
"@babel/types" "^7.7.0"
convert-source-map "^1.1.0"
"@babel/traverse" "^7.7.2"
"@babel/types" "^7.7.2"
convert-source-map "^1.7.0"
debug "^4.1.0"
json5 "^2.1.0"
lodash "^4.17.13"
@ -29,12 +29,12 @@
semver "^5.4.1"
source-map "^0.5.0"
"@babel/generator@^7.7.0":
version "7.7.0"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.0.tgz#c6d4d1f7a0d6e139cbd01aca73170b0bff5425b4"
integrity sha512-1wdJ6UxHyL1XoJQ119JmvuRX27LRih7iYStMPZOWAjQqeAabFg3dYXKMpgihma+to+0ADsTVVt6oRyUxWZw6Mw==
"@babel/generator@^7.7.0", "@babel/generator@^7.7.2":
version "7.7.2"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.2.tgz#2f4852d04131a5e17ea4f6645488b5da66ebf3af"
integrity sha512-WthSArvAjYLz4TcbKOi88me+KmDJdKSlfwwN8CnUYn9jBkzhq0ZEPuBfkAWIvjJ3AdEV1Cf/+eSQTnp3IDJKlQ==
dependencies:
"@babel/types" "^7.7.0"
"@babel/types" "^7.7.2"
jsesc "^2.5.1"
lodash "^4.17.13"
source-map "^0.5.0"
@ -240,11 +240,16 @@
esutils "^2.0.2"
js-tokens "^4.0.0"
"@babel/parser@^7.0.0", "@babel/parser@^7.7.0":
"@babel/parser@^7.0.0":
version "7.7.0"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.0.tgz#232618f6e8947bc54b407fa1f1c91a22758e7159"
integrity sha512-GqL+Z0d7B7ADlQBMXlJgvXEbtt5qlqd1YQ5fr12hTSfh7O/vgrEIvJxU2e7aSVrEUn75zTZ6Nd0s8tthrlZnrQ==
"@babel/parser@^7.7.0", "@babel/parser@^7.7.2":
version "7.7.2"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.2.tgz#ea8334dc77416bfd9473eb470fd00d8245b3943b"
integrity sha512-DDaR5e0g4ZTb9aP7cpSZLkACEBdoLGwJDWgHtBhrGX7Q1RjhdoMOfexICj5cqTAtpowjGQWfcvfnQG7G2kAB5w==
"@babel/plugin-proposal-async-generator-functions@^7.7.0":
version "7.7.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.0.tgz#83ef2d6044496b4c15d8b4904e2219e6dccc6971"
@ -720,13 +725,20 @@
"@babel/plugin-transform-react-jsx-self" "^7.0.0"
"@babel/plugin-transform-react-jsx-source" "^7.0.0"
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.5", "@babel/runtime@^7.7.1":
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.5":
version "7.7.1"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.7.1.tgz#b223497bbfbcbbb38116673904debc71470ca528"
integrity sha512-SQ0sS7KUJDvgCI2cpZG0nJygO6002oTbhgSuw4WcocsnbxLwL5Q8I3fqbJdyBAc3uFrWZiR2JomseuxSuci3SQ==
dependencies:
regenerator-runtime "^0.13.2"
"@babel/runtime@^7.7.1":
version "7.7.2"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.7.2.tgz#111a78002a5c25fc8e3361bedc9529c696b85a6a"
integrity sha512-JONRbXbTXc9WQE2mAZd1p0Z3DZ/6vaQIkgYMSTP3KjRCyd7rCZCcfhCyX+YjwcKxcZ82UrxbRD358bpExNgrjw==
dependencies:
regenerator-runtime "^0.13.2"
"@babel/template@^7.7.0":
version "7.7.0"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.0.tgz#4fadc1b8e734d97f56de39c77de76f2562e597d0"
@ -736,7 +748,7 @@
"@babel/parser" "^7.7.0"
"@babel/types" "^7.7.0"
"@babel/traverse@^7.0.0", "@babel/traverse@^7.7.0":
"@babel/traverse@^7.0.0":
version "7.7.0"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.0.tgz#9f5744346b8d10097fd2ec2eeffcaf19813cbfaf"
integrity sha512-ea/3wRZc//e/uwCpuBX2itrhI0U9l7+FsrKWyKGNyvWbuMcCG7ATKY2VI4wlg2b2TA39HHwIxnvmXvtiKsyn7w==
@ -751,7 +763,22 @@
globals "^11.1.0"
lodash "^4.17.13"
"@babel/types@^7.0.0", "@babel/types@^7.7.0", "@babel/types@^7.7.1":
"@babel/traverse@^7.7.0", "@babel/traverse@^7.7.2":
version "7.7.2"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.2.tgz#ef0a65e07a2f3c550967366b3d9b62a2dcbeae09"
integrity sha512-TM01cXib2+rgIZrGJOLaHV/iZUAxf4A0dt5auY6KNZ+cm6aschuJGqKJM3ROTt3raPUdIDk9siAufIFEleRwtw==
dependencies:
"@babel/code-frame" "^7.5.5"
"@babel/generator" "^7.7.2"
"@babel/helper-function-name" "^7.7.0"
"@babel/helper-split-export-declaration" "^7.7.0"
"@babel/parser" "^7.7.2"
"@babel/types" "^7.7.2"
debug "^4.1.0"
globals "^11.1.0"
lodash "^4.17.13"
"@babel/types@^7.0.0", "@babel/types@^7.7.1":
version "7.7.1"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.1.tgz#8b08ea368f2baff236613512cf67109e76285827"
integrity sha512-kN/XdANDab9x1z5gcjDc9ePpxexkt+1EQ2MQUiM4XnMvQfvp87/+6kY4Ko2maLXH+tei/DgJ/ybFITeqqRwDiA==
@ -760,7 +787,16 @@
lodash "^4.17.13"
to-fast-properties "^2.0.0"
"@hot-loader/react-dom@^16.9.0":
"@babel/types@^7.7.0", "@babel/types@^7.7.2":
version "7.7.2"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.2.tgz#550b82e5571dcd174af576e23f0adba7ffc683f7"
integrity sha512-YTf6PXoh3+eZgRCBzzP25Bugd2ngmpQVrk7kXX0i5N9BO7TFBtIgZYs7WtxtOGs8e6A4ZI7ECkbBCEHeXocvOA==
dependencies:
esutils "^2.0.2"
lodash "^4.17.13"
to-fast-properties "^2.0.0"
"@hot-loader/react-dom@16.10.2":
version "16.10.2"
resolved "https://registry.yarnpkg.com/@hot-loader/react-dom/-/react-dom-16.10.2.tgz#91920442252acac6f343eef5df41aca333f7dcea"
integrity sha512-vbrSDuZMoE1TXiDNAVCSAcIS6UX55Fa9KF0MD0wQgOaOIPZs/C6CtEDUcnNFEwTQ5ciIULcp+96lQlSuANNagA==
@ -894,11 +930,24 @@
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==
"@types/prop-types@*":
version "15.7.3"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==
"@types/q@^1.5.1":
version "1.5.2"
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8"
integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==
"@types/react@^15.0.0 || ^16.0.0":
version "16.9.11"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.11.tgz#70e0b7ad79058a7842f25ccf2999807076ada120"
integrity sha512-UBT4GZ3PokTXSWmdgC/GeCGEJXE5ofWyibCcecRLUVN2ZBpXQGVgQGtG2foS7CrTKFKlQVVswLvf7Js6XA/CVQ==
dependencies:
"@types/prop-types" "*"
csstype "^2.2.0"
"@types/source-list-map@*":
version "0.1.2"
resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9"
@ -1633,27 +1682,7 @@ bytes@3.1.0:
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
cacache@^11.3.3:
version "11.3.3"
resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.3.tgz#8bd29df8c6a718a6ebd2d010da4d7972ae3bbadc"
integrity sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==
dependencies:
bluebird "^3.5.5"
chownr "^1.1.1"
figgy-pudding "^3.5.1"
glob "^7.1.4"
graceful-fs "^4.1.15"
lru-cache "^5.1.1"
mississippi "^3.0.0"
mkdirp "^0.5.1"
move-concurrently "^1.0.1"
promise-inflight "^1.0.1"
rimraf "^2.6.3"
ssri "^6.0.1"
unique-filename "^1.1.1"
y18n "^4.0.0"
cacache@^12.0.2:
cacache@^12.0.2, cacache@^12.0.3:
version "12.0.3"
resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390"
integrity sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==
@ -2070,7 +2099,7 @@ content-type@~1.0.4:
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
convert-source-map@^1.1.0:
convert-source-map@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
@ -2105,11 +2134,11 @@ copy-descriptor@^0.1.0:
integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
copy-webpack-plugin@^5.0.4:
version "5.0.4"
resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-5.0.4.tgz#c78126f604e24f194c6ec2f43a64e232b5d43655"
integrity sha512-YBuYGpSzoCHSSDGyHy6VJ7SHojKp6WHT4D7ItcQFNAYx2hrwkMe56e97xfVR0/ovDuMTrMffXUiltvQljtAGeg==
version "5.0.5"
resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-5.0.5.tgz#731df6a837a2ef0f8f8e2345bdfe9b7c62a2da68"
integrity sha512-7N68eIoQTyudAuxkfPT7HzGoQ+TsmArN/I3HFwG+lVE3FNzqvZKIiaxtYh4o3BIznioxUvx9j26+Rtsc9htQUQ==
dependencies:
cacache "^11.3.3"
cacache "^12.0.3"
find-cache-dir "^2.1.0"
glob-parent "^3.1.0"
globby "^7.1.1"
@ -2117,9 +2146,9 @@ copy-webpack-plugin@^5.0.4:
loader-utils "^1.2.3"
minimatch "^3.0.4"
normalize-path "^3.0.0"
p-limit "^2.2.0"
p-limit "^2.2.1"
schema-utils "^1.0.0"
serialize-javascript "^1.7.0"
serialize-javascript "^2.1.0"
webpack-log "^2.0.0"
core-js-compat@^3.1.1:
@ -2131,9 +2160,9 @@ core-js-compat@^3.1.1:
semver "^6.3.0"
core-js@^3.3.6:
version "3.3.6"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.3.6.tgz#6ad1650323c441f45379e176ed175c0d021eac92"
integrity sha512-u4oM8SHwmDuh5mWZdDg9UwNVq5s1uqq6ZDLLIs07VY+VJU91i3h4f3K/pgFvtUQPGdeStrZ+odKyfyt4EnKHfA==
version "3.4.0"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.4.0.tgz#29ea478601789c72f2978e9bb98f43546f89d3aa"
integrity sha512-lQxb4HScV71YugF/X28LtePZj9AB7WqOpcB+YztYxusvhrgZiQXPmCYfPC5LHsw/+ScEtDbXU3xbqH3CjBRmYA==
core-util-is@~1.0.0:
version "1.0.2"
@ -2377,6 +2406,11 @@ csso@^4.0.2:
dependencies:
css-tree "1.0.0-alpha.37"
csstype@^2.2.0:
version "2.6.7"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.7.tgz#20b0024c20b6718f4eda3853a1f5a1cce7f5e4a5"
integrity sha512-9Mcn9sFbGBAdmimWb2gLVDtFJzeKtDGIr76TUqmjZrw9LFXBMSU70lcs+C0/7fyCd6iBDqmksUcCOUIkisPHsQ==
cyclist@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
@ -2392,6 +2426,11 @@ date-fns@^1.27.2:
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c"
integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==
date-fns@^2.7.0:
version "2.7.0"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.7.0.tgz#8271d943cc4636a1f27698f1b8d6a9f1ceb74026"
integrity sha512-wxYp2PGoUDN5ZEACc61aOtYFvSsJUylIvCjpjDOqM1UDaKIIuMJ9fAnMYFHV3TQaDpfTVxhwNK/GiCaHKuemTA==
debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@ -2877,9 +2916,9 @@ eslint-plugin-import@^2.18.0:
resolve "^1.11.0"
eslint-plugin-jest@^23.0.2:
version "23.0.2"
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.0.2.tgz#54a59bfe77245186afe13711a297067aefefff0a"
integrity sha512-fkxcvOJm0hC/jbJqYJjtuC9mvpTJqXd0Nixx7joVQvJoBQuXk/ws3+MtRYzD/4TcKSgvr21uuSLdwSxKJKC2cg==
version "23.0.3"
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.0.3.tgz#d3f157f7791f97713372c13259ba1dfc436eb4c1"
integrity sha512-9cNxr66zeOyz1S9AkQL4/ouilR6QHpYj8vKOQZ60fu9hAt5PJWS4KqWqfr1aqN5NFEZSPjFOla2Azn+KTWiGwg==
dependencies:
"@typescript-eslint/experimental-utils" "^2.5.0"
@ -3499,7 +3538,7 @@ glob-parent@^5.0.0, glob-parent@^5.1.0:
dependencies:
is-glob "^4.0.1"
glob@^7.0.3, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
glob@^7.0.3:
version "7.1.5"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.5.tgz#6714c69bee20f3c3e64c4dd905553e532b40cdc0"
integrity sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ==
@ -3511,6 +3550,18 @@ glob@^7.0.3, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
once "^1.3.0"
path-is-absolute "^1.0.0"
glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
version "7.1.6"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^3.0.4"
once "^1.3.0"
path-is-absolute "^1.0.0"
global-modules@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780"
@ -5431,7 +5482,7 @@ p-limit@^1.1.0:
dependencies:
p-try "^1.0.0"
p-limit@^2.0.0, p-limit@^2.2.0:
p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537"
integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==
@ -5903,9 +5954,9 @@ postcss-modules-values@^3.0.0:
postcss "^7.0.6"
postcss-nested@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-4.2.0.tgz#e6e6777b05dddd47358c676d983bd7251d0e67a2"
integrity sha512-qRAOC0uJ4TbFXlURB+3Y5sCi9+MLTkXmt7VGpqHw5oAWCnHqeFa4MGf7kb5ceFDthknumJc+E4A0TjV4XEVWBQ==
version "4.2.1"
resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-4.2.1.tgz#4bc2e5b35e3b1e481ff81e23b700da7f82a8b248"
integrity sha512-AMayXX8tS0HCp4O4lolp4ygj9wBn32DJWXvG6gCv+ZvJrEa00GUxJcJEEzMh87BIe6FrWdYkpR2cuyqHKrxmXw==
dependencies:
postcss "^7.0.21"
postcss-selector-parser "^6.0.2"
@ -6352,11 +6403,19 @@ react-dom@^0.0.0-experimental-f6b8d31a7:
prop-types "^15.6.2"
scheduler "0.0.0-experimental-f6b8d31a7"
react-hot-loader@^4.12.14:
version "4.12.15"
resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.12.15.tgz#6bf3984e52edbdf02ea8952777f53da1b3c68c95"
integrity sha512-sgkN6g+tgPE6xZzD0Ysqll7KUFYJbMX0DrczT5OxD6S7hZlSnmqSC3ceudwCkiDd65ZTtm+Ayk4Y9k5xxCvpOw==
react-feather@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/react-feather/-/react-feather-2.0.3.tgz#1453ff5d8c242f72b8c02846118fbd2d406375ad"
integrity sha512-XVjtxIyMxb2RFlqC2APoB/IZvXKDW9uLN1c264XEeZNYe8jIxjQVQpeTo3nxtHiLTgMfgf0ZYxJC6HwmY8+9BA==
dependencies:
prop-types "^15.7.2"
react-hot-loader@^4.12.14:
version "4.12.16"
resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.12.16.tgz#353bd07fbb08f791b5720535f86b0a8f9b651317"
integrity sha512-KC33uTBacgdunMtfpZFP2pgPpyvKIcCwuh0XmWESbeFrkWLqUtCFN91zyaTdU5OiAM982+E8xh1gjE5EINumaw==
dependencies:
"@types/react" "^15.0.0 || ^16.0.0"
fast-levenshtein "^2.0.6"
global "^4.3.0"
hoist-non-react-statics "^3.3.0"
@ -6415,6 +6474,11 @@ react-router@5.1.2:
tiny-invariant "^1.0.2"
tiny-warning "^1.0.0"
react-table@^7.0.0-beta.12:
version "7.0.0-beta.12"
resolved "https://registry.yarnpkg.com/react-table/-/react-table-7.0.0-beta.12.tgz#ae54b398fbdb527b9fad82e52c4d829c00fdd5dc"
integrity sha512-h1c0KNTBRPAMgZumaNixr3X0w7kFTuqk6pHwia12LsMgnTHNEEeqp7+tQ5fTPwwMArp1/OHXeOdSKEes1C83iw==
react-window@^1.8.5:
version "1.8.5"
resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.5.tgz#a56b39307e79979721021f5d06a67742ecca52d1"