Add support for showing usage graphs on the console page
This commit is contained in:
parent
c66d2cd123
commit
29834a33f8
|
@ -6,12 +6,14 @@
|
||||||
"@fortawesome/react-fontawesome": "^0.1.4",
|
"@fortawesome/react-fontawesome": "^0.1.4",
|
||||||
"@hot-loader/react-dom": "^16.8.6",
|
"@hot-loader/react-dom": "^16.8.6",
|
||||||
"axios": "^0.18.0",
|
"axios": "^0.18.0",
|
||||||
|
"chart.js": "^2.8.0",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"date-fns": "^1.29.0",
|
"date-fns": "^1.29.0",
|
||||||
"easy-peasy": "^3.0.2",
|
"easy-peasy": "^3.0.2",
|
||||||
"events": "^3.0.0",
|
"events": "^3.0.0",
|
||||||
"formik": "^1.5.7",
|
"formik": "^1.5.7",
|
||||||
"jquery": "^3.3.1",
|
"jquery": "^3.3.1",
|
||||||
|
"lodash-es": "^4.17.15",
|
||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
"query-string": "^6.7.0",
|
"query-string": "^6.7.0",
|
||||||
"react": "^16.8.6",
|
"react": "^16.8.6",
|
||||||
|
@ -39,10 +41,12 @@
|
||||||
"@babel/preset-react": "^7.0.0",
|
"@babel/preset-react": "^7.0.0",
|
||||||
"@babel/preset-typescript": "^7.6.0",
|
"@babel/preset-typescript": "^7.6.0",
|
||||||
"@babel/runtime": "^7.6.0",
|
"@babel/runtime": "^7.6.0",
|
||||||
|
"@types/chart.js": "^2.8.5",
|
||||||
"@types/classnames": "^2.2.8",
|
"@types/classnames": "^2.2.8",
|
||||||
"@types/events": "^3.0.0",
|
"@types/events": "^3.0.0",
|
||||||
"@types/feather-icons": "^4.7.0",
|
"@types/feather-icons": "^4.7.0",
|
||||||
"@types/lodash": "^4.14.119",
|
"@types/lodash": "^4.14.119",
|
||||||
|
"@types/lodash-es": "^4.17.3",
|
||||||
"@types/node": "^12.6.9",
|
"@types/node": "^12.6.9",
|
||||||
"@types/query-string": "^6.3.0",
|
"@types/query-string": "^6.3.0",
|
||||||
"@types/react": "^16.8.19",
|
"@types/react": "^16.8.19",
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
import { IconProp } from '@fortawesome/fontawesome-svg-core';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
icon?: IconProp;
|
||||||
|
title: string;
|
||||||
|
className?: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ({ icon, title, children, className }: Props) => (
|
||||||
|
<div className={`rounded shadow-md bg-neutral-700 ${className}`}>
|
||||||
|
<div className={'bg-neutral-900 rounded-t p-3 border-b border-black'}>
|
||||||
|
<p className={'text-sm uppercase'}>
|
||||||
|
{icon && <FontAwesomeIcon icon={icon} className={'mr-2 text-neutral-300'}/>}{title}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className={'p-3'}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
|
@ -4,19 +4,16 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { faServer } from '@fortawesome/free-solid-svg-icons/faServer';
|
import { faServer } from '@fortawesome/free-solid-svg-icons/faServer';
|
||||||
import { faCircle } from '@fortawesome/free-solid-svg-icons/faCircle';
|
import { faCircle } from '@fortawesome/free-solid-svg-icons/faCircle';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import styled from 'styled-components';
|
|
||||||
import { faMemory } from '@fortawesome/free-solid-svg-icons/faMemory';
|
import { faMemory } from '@fortawesome/free-solid-svg-icons/faMemory';
|
||||||
import { faMicrochip } from '@fortawesome/free-solid-svg-icons/faMicrochip';
|
import { faMicrochip } from '@fortawesome/free-solid-svg-icons/faMicrochip';
|
||||||
import { bytesToHuman } from '@/helpers';
|
import { bytesToHuman } from '@/helpers';
|
||||||
import SuspenseSpinner from '@/components/elements/SuspenseSpinner';
|
import SuspenseSpinner from '@/components/elements/SuspenseSpinner';
|
||||||
|
import TitledGreyBox from '@/components/elements/TitledGreyBox';
|
||||||
|
|
||||||
type PowerAction = 'start' | 'stop' | 'restart' | 'kill';
|
type PowerAction = 'start' | 'stop' | 'restart' | 'kill';
|
||||||
|
|
||||||
const GreyBox = styled.div`
|
|
||||||
${tw`mt-4 shadow-md bg-neutral-700 rounded p-3 flex text-xs`}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const ChunkedConsole = lazy(() => import('@/components/server/Console'));
|
const ChunkedConsole = lazy(() => import('@/components/server/Console'));
|
||||||
|
const ChunkedStatGraphs = lazy(() => import('@/components/server/StatGraphs'));
|
||||||
|
|
||||||
const StopOrKillButton = ({ onPress }: { onPress: (action: PowerAction) => void }) => {
|
const StopOrKillButton = ({ onPress }: { onPress: (action: PowerAction) => void }) => {
|
||||||
const [ clicked, setClicked ] = useState(false);
|
const [ clicked, setClicked ] = useState(false);
|
||||||
|
@ -80,46 +77,39 @@ export default () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'my-10 flex'}>
|
<div className={'my-10 flex'}>
|
||||||
<div className={'flex-1 ml-4'}>
|
<div className={'w-1/4 ml-4'}>
|
||||||
<div className={'rounded shadow-md bg-neutral-700'}>
|
<TitledGreyBox title={server.name} icon={faServer}>
|
||||||
<div className={'bg-neutral-900 rounded-t p-3 border-b border-black'}>
|
<p className={'text-xs uppercase'}>
|
||||||
<p className={'text-sm uppercase'}>
|
<FontAwesomeIcon
|
||||||
<FontAwesomeIcon icon={faServer} className={'mr-1 text-neutral-300'}/> {server.name}
|
icon={faCircle}
|
||||||
</p>
|
fixedWidth={true}
|
||||||
</div>
|
className={classNames('mr-1', {
|
||||||
<div className={'p-3'}>
|
'text-red-500': status === 'offline',
|
||||||
<p className={'text-xs uppercase'}>
|
'text-yellow-500': [ 'running', 'offline' ].indexOf(status) < 0,
|
||||||
<FontAwesomeIcon
|
'text-green-500': status === 'running',
|
||||||
icon={faCircle}
|
})}
|
||||||
fixedWidth={true}
|
/>
|
||||||
className={classNames('mr-1', {
|
{status}
|
||||||
'text-red-500': status === 'offline',
|
</p>
|
||||||
'text-yellow-500': [ 'running', 'offline' ].indexOf(status) < 0,
|
<p className={'text-xs mt-2'}>
|
||||||
'text-green-500': status === 'running',
|
<FontAwesomeIcon
|
||||||
})}
|
icon={faMemory}
|
||||||
/>
|
fixedWidth={true}
|
||||||
{status}
|
className={'mr-1'}
|
||||||
</p>
|
/>
|
||||||
<p className={'text-xs mt-2'}>
|
{bytesToHuman(memory)}
|
||||||
<FontAwesomeIcon
|
<span className={'text-neutral-500'}>/ {server.limits.memory} MB</span>
|
||||||
icon={faMemory}
|
</p>
|
||||||
fixedWidth={true}
|
<p className={'text-xs mt-2'}>
|
||||||
className={'mr-1'}
|
<FontAwesomeIcon
|
||||||
/>
|
icon={faMicrochip}
|
||||||
{bytesToHuman(memory)}
|
fixedWidth={true}
|
||||||
<span className={'text-neutral-500'}>/ {server.limits.memory} MB</span>
|
className={'mr-1'}
|
||||||
</p>
|
/>
|
||||||
<p className={'text-xs mt-2'}>
|
{cpu.toFixed(2)} %
|
||||||
<FontAwesomeIcon
|
</p>
|
||||||
icon={faMicrochip}
|
</TitledGreyBox>
|
||||||
fixedWidth={true}
|
<div className={'grey-box justify-center'}>
|
||||||
className={'mr-1'}
|
|
||||||
/>
|
|
||||||
{cpu.toFixed(2)} %
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<GreyBox className={'justify-center'}>
|
|
||||||
<button
|
<button
|
||||||
className={'btn btn-secondary btn-xs mr-2'}
|
className={'btn btn-secondary btn-xs mr-2'}
|
||||||
disabled={status !== 'offline'}
|
disabled={status !== 'offline'}
|
||||||
|
@ -140,13 +130,14 @@ export default () => {
|
||||||
Restart
|
Restart
|
||||||
</button>
|
</button>
|
||||||
<StopOrKillButton onPress={action => sendPowerCommand(action)}/>
|
<StopOrKillButton onPress={action => sendPowerCommand(action)}/>
|
||||||
</GreyBox>
|
|
||||||
</div>
|
|
||||||
<SuspenseSpinner>
|
|
||||||
<div className={'mx-4 w-3/4 mr-4'}>
|
|
||||||
<ChunkedConsole/>
|
|
||||||
</div>
|
</div>
|
||||||
</SuspenseSpinner>
|
</div>
|
||||||
|
<div className={'flex-1 mx-4 mr-4'}>
|
||||||
|
<SuspenseSpinner>
|
||||||
|
<ChunkedConsole/>
|
||||||
|
{status !== 'offline' && <ChunkedStatGraphs/>}
|
||||||
|
</SuspenseSpinner>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,171 @@
|
||||||
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
|
import Chart, { ChartConfiguration } from 'chart.js';
|
||||||
|
import { ServerContext } from '@/state/server';
|
||||||
|
import { bytesToMegabytes } from '@/helpers';
|
||||||
|
import merge from 'lodash-es/merge';
|
||||||
|
import TitledGreyBox from '@/components/elements/TitledGreyBox';
|
||||||
|
import { faMemory } from '@fortawesome/free-solid-svg-icons/faMemory';
|
||||||
|
import { faMicrochip } from '@fortawesome/free-solid-svg-icons/faMicrochip';
|
||||||
|
|
||||||
|
const chartDefaults: ChartConfiguration = {
|
||||||
|
type: 'line',
|
||||||
|
options: {
|
||||||
|
legend: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
tooltips: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
animation: {
|
||||||
|
duration: 0,
|
||||||
|
},
|
||||||
|
hover: {
|
||||||
|
animationDuration: 0,
|
||||||
|
},
|
||||||
|
elements: {
|
||||||
|
point: {
|
||||||
|
radius: 0,
|
||||||
|
},
|
||||||
|
line: {
|
||||||
|
tension: 0.1,
|
||||||
|
backgroundColor: 'rgba(15, 178, 184, 0.45)',
|
||||||
|
borderColor: '#32D0D9',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
xAxes: [ {
|
||||||
|
ticks: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
gridLines: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
} ],
|
||||||
|
yAxes: [ {
|
||||||
|
gridLines: {
|
||||||
|
drawTicks: false,
|
||||||
|
color: 'rgba(229, 232, 235, 0.15)',
|
||||||
|
zeroLineColor: 'rgba(15, 178, 184, 0.45)',
|
||||||
|
zeroLineWidth: 3,
|
||||||
|
},
|
||||||
|
ticks: {
|
||||||
|
fontSize: 10,
|
||||||
|
fontFamily: '"IBM Plex Mono", monospace',
|
||||||
|
fontColor: 'rgb(229, 232, 235)',
|
||||||
|
min: 0,
|
||||||
|
beginAtZero: true,
|
||||||
|
maxTicksLimit: 5,
|
||||||
|
},
|
||||||
|
} ],
|
||||||
|
},
|
||||||
|
responsiveAnimationDuration: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const createDefaultChart = (ctx: CanvasRenderingContext2D, options?: ChartConfiguration): Chart => new Chart(ctx, {
|
||||||
|
...merge({}, chartDefaults, options),
|
||||||
|
data: {
|
||||||
|
labels: Array(20).fill(''),
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
fill: true,
|
||||||
|
data: Array(20).fill(0),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const { limits } = ServerContext.useStoreState(state => state.server.data!);
|
||||||
|
const { connected, instance } = ServerContext.useStoreState(state => state.socket);
|
||||||
|
|
||||||
|
const [ memory, setMemory ] = useState<Chart>();
|
||||||
|
const [ cpu, setCpu ] = useState<Chart>();
|
||||||
|
|
||||||
|
const memoryRef = useCallback<(node: HTMLCanvasElement | null) => void>(node => {
|
||||||
|
if (!node) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setMemory(createDefaultChart(node.getContext('2d')!, {
|
||||||
|
options: {
|
||||||
|
scales: {
|
||||||
|
yAxes: [ {
|
||||||
|
ticks: {
|
||||||
|
callback: (value) => `${value}Mb `,
|
||||||
|
suggestedMax: limits.memory,
|
||||||
|
},
|
||||||
|
} ],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const cpuRef = useCallback<(node: HTMLCanvasElement | null) => void>(node => {
|
||||||
|
if (!node) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setCpu(createDefaultChart(node.getContext('2d')!, {
|
||||||
|
options: {
|
||||||
|
scales: {
|
||||||
|
yAxes: [ {
|
||||||
|
ticks: {
|
||||||
|
callback: (value) => `${value}% `,
|
||||||
|
},
|
||||||
|
} ],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const statsListener = (data: string) => {
|
||||||
|
let stats: any = {};
|
||||||
|
try {
|
||||||
|
stats = JSON.parse(data);
|
||||||
|
} catch (e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memory && memory.data.datasets) {
|
||||||
|
const data = memory.data.datasets[0].data!;
|
||||||
|
|
||||||
|
data.push(bytesToMegabytes(stats.memory_bytes));
|
||||||
|
data.shift();
|
||||||
|
|
||||||
|
memory.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cpu && cpu.data.datasets) {
|
||||||
|
const data = cpu.data.datasets[0].data!;
|
||||||
|
|
||||||
|
data.push(stats.cpu_absolute);
|
||||||
|
data.shift();
|
||||||
|
|
||||||
|
cpu.update();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!connected || !instance) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance.addListener('stats', statsListener);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
instance.removeListener('stats', statsListener);
|
||||||
|
};
|
||||||
|
}, [ connected, memory, cpu ]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={'flex mt-4'}>
|
||||||
|
<TitledGreyBox title={'Memory usage'} icon={faMemory} className={'flex-1 mr-2'}>
|
||||||
|
<canvas id={'memory_chart'} ref={memoryRef} aria-label={'Server Memory Usage Graph'} role={'img'}/>
|
||||||
|
</TitledGreyBox>
|
||||||
|
<TitledGreyBox title={'CPU usage'} icon={faMicrochip} className={'flex-1 ml-2'}>
|
||||||
|
<canvas id={'cpu_chart'} ref={cpuRef} aria-label={'Server CPU Usage Graph'} role={'img'}/>
|
||||||
|
</TitledGreyBox>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -4,7 +4,8 @@ export function bytesToHuman (bytes: number): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
const i = Math.floor(Math.log(bytes) / Math.log(1000));
|
const i = Math.floor(Math.log(bytes) / Math.log(1000));
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return `${(bytes / Math.pow(1000, i)).toFixed(2) * 1} ${['Bytes', 'kB', 'MB', 'GB', 'TB'][i]}`;
|
return `${(bytes / Math.pow(1000, i)).toFixed(2) * 1} ${['Bytes', 'kB', 'MB', 'GB', 'TB'][i]}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const bytesToMegabytes = (bytes: number) => Math.floor(bytes / 1000 / 1000);
|
||||||
|
|
|
@ -19,3 +19,7 @@ code.clean {
|
||||||
@apply .rounded-full .bg-neutral-500 .p-3;
|
@apply .rounded-full .bg-neutral-500 .p-3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.grey-box {
|
||||||
|
@apply .mt-4 .shadow-md .bg-neutral-700 .rounded .p-3 .flex .text-xs;
|
||||||
|
}
|
46
yarn.lock
46
yarn.lock
|
@ -958,6 +958,10 @@
|
||||||
prop-types "^15.6.2"
|
prop-types "^15.6.2"
|
||||||
scheduler "^0.13.6"
|
scheduler "^0.13.6"
|
||||||
|
|
||||||
|
"@types/chart.js@^2.8.5":
|
||||||
|
version "2.8.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/chart.js/-/chart.js-2.8.5.tgz#7d47cfd36f0a1c2c4ad6a585749bc68e8659492a"
|
||||||
|
|
||||||
"@types/classnames@^2.2.8":
|
"@types/classnames@^2.2.8":
|
||||||
version "2.2.8"
|
version "2.2.8"
|
||||||
resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.8.tgz#17139e1e1104203572caa4368f6796f6225b70b4"
|
resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.8.tgz#17139e1e1104203572caa4368f6796f6225b70b4"
|
||||||
|
@ -993,6 +997,16 @@
|
||||||
"@types/react" "*"
|
"@types/react" "*"
|
||||||
hoist-non-react-statics "^3.3.0"
|
hoist-non-react-statics "^3.3.0"
|
||||||
|
|
||||||
|
"@types/lodash-es@^4.17.3":
|
||||||
|
version "4.17.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/lodash-es/-/lodash-es-4.17.3.tgz#87eb0b3673b076b8ee655f1890260a136af09a2d"
|
||||||
|
dependencies:
|
||||||
|
"@types/lodash" "*"
|
||||||
|
|
||||||
|
"@types/lodash@*":
|
||||||
|
version "4.14.141"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.141.tgz#d81f4d0c562abe28713406b571ffb27692a82ae6"
|
||||||
|
|
||||||
"@types/lodash@^4.14.119":
|
"@types/lodash@^4.14.119":
|
||||||
version "4.14.119"
|
version "4.14.119"
|
||||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.119.tgz#be847e5f4bc3e35e46d041c394ead8b603ad8b39"
|
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.119.tgz#be847e5f4bc3e35e46d041c394ead8b603ad8b39"
|
||||||
|
@ -2143,6 +2157,26 @@ chardet@^0.7.0:
|
||||||
version "0.7.0"
|
version "0.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
|
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
|
||||||
|
|
||||||
|
chart.js@^2.8.0:
|
||||||
|
version "2.8.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.8.0.tgz#b703b10d0f4ec5079eaefdcd6ca32dc8f826e0e9"
|
||||||
|
dependencies:
|
||||||
|
chartjs-color "^2.1.0"
|
||||||
|
moment "^2.10.2"
|
||||||
|
|
||||||
|
chartjs-color-string@^0.6.0:
|
||||||
|
version "0.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz#1df096621c0e70720a64f4135ea171d051402f71"
|
||||||
|
dependencies:
|
||||||
|
color-name "^1.0.0"
|
||||||
|
|
||||||
|
chartjs-color@^2.1.0:
|
||||||
|
version "2.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/chartjs-color/-/chartjs-color-2.3.0.tgz#0e7e1e8dba37eae8415fd3db38bf572007dd958f"
|
||||||
|
dependencies:
|
||||||
|
chartjs-color-string "^0.6.0"
|
||||||
|
color-convert "^0.5.3"
|
||||||
|
|
||||||
chokidar@^2.0.2:
|
chokidar@^2.0.2:
|
||||||
version "2.0.3"
|
version "2.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.3.tgz#dcbd4f6cbb2a55b4799ba8a840ac527e5f4b1176"
|
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.3.tgz#dcbd4f6cbb2a55b4799ba8a840ac527e5f4b1176"
|
||||||
|
@ -2284,6 +2318,10 @@ collection-visit@^1.0.0:
|
||||||
map-visit "^1.0.0"
|
map-visit "^1.0.0"
|
||||||
object-visit "^1.0.0"
|
object-visit "^1.0.0"
|
||||||
|
|
||||||
|
color-convert@^0.5.3:
|
||||||
|
version "0.5.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-0.5.3.tgz#bdb6c69ce660fadffe0b0007cc447e1b9f7282bd"
|
||||||
|
|
||||||
color-convert@^1.8.2, color-convert@^1.9.0:
|
color-convert@^1.8.2, color-convert@^1.9.0:
|
||||||
version "1.9.1"
|
version "1.9.1"
|
||||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed"
|
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed"
|
||||||
|
@ -4801,6 +4839,10 @@ lodash-es@^4.17.11:
|
||||||
version "4.17.11"
|
version "4.17.11"
|
||||||
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.11.tgz#145ab4a7ac5c5e52a3531fb4f310255a152b4be0"
|
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.11.tgz#145ab4a7ac5c5e52a3531fb4f310255a152b4be0"
|
||||||
|
|
||||||
|
lodash-es@^4.17.15:
|
||||||
|
version "4.17.15"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78"
|
||||||
|
|
||||||
lodash._baseassign@^3.0.0:
|
lodash._baseassign@^3.0.0:
|
||||||
version "3.2.0"
|
version "3.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e"
|
resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e"
|
||||||
|
@ -5232,6 +5274,10 @@ mkdirp@0.5.x, mkdirp@^0.5, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~
|
||||||
dependencies:
|
dependencies:
|
||||||
minimist "0.0.8"
|
minimist "0.0.8"
|
||||||
|
|
||||||
|
moment@^2.10.2:
|
||||||
|
version "2.24.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
|
||||||
|
|
||||||
move-concurrently@^1.0.1:
|
move-concurrently@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
|
resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
|
||||||
|
|
Loading…
Reference in New Issue