From 43f861fcc02e98809a08bfd7ce4d57e97af548bf Mon Sep 17 00:00:00 2001 From: Ginger Wong Date: Sat, 3 Oct 2020 20:59:25 -0700 Subject: [PATCH 01/14] initial files --- web/README.md | 12 +++++++- web/pages/index2.tsx | 32 +++++++++++++++++++++ web/pages/utils/apis.ts | 62 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 web/pages/index2.tsx create mode 100644 web/pages/utils/apis.ts diff --git a/web/README.md b/web/README.md index 13d24a0ab..51b274fe9 100644 --- a/web/README.md +++ b/web/README.md @@ -10,7 +10,7 @@ npm run dev yarn dev ``` -Open [http://localhost:3000/admin](http://localhost:3000/admin) with your browser to see the result. +In production this Admin instance would ideally live on the domain as your Owncast instance, for example: `myowncast-site.com/admin`. So open [http://localhost:3000/admin](http://localhost:3000/admin) with your browser to see the result. You can start editing a page by modifying `pages/something.js`. The page auto-updates as you edit the file. @@ -18,6 +18,15 @@ Add new pages by adding files to the `pages` directory and [routes](https://next Since this project hits API endpoints you should make requests in [`componentDidMount`](https://reactjs.org/docs/react-component.html#componentdidmount), and not in [`getStaticProps`](https://nextjs.org/docs/basic-features/data-fetching), since they're not static and we don't want to fetch them at build time, but instead at runtime. + +A list of API end points can be found here: +https://github.com/owncast/owncast/blob/master/router/router.go + +### Auth-ing for APIs +username: admin +pw: [your stramkey] + + ## Learn More To learn more about Next.js, take a look at the following resources: @@ -26,3 +35,4 @@ To learn more about Next.js, take a look at the following resources: - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! + diff --git a/web/pages/index2.tsx b/web/pages/index2.tsx new file mode 100644 index 000000000..bb35f0dc3 --- /dev/null +++ b/web/pages/index2.tsx @@ -0,0 +1,32 @@ +import React, { useState, useEffect } from 'react'; +import { BROADCASTER, fetchData } from './utils/apis'; + +export default function Admin() { + const [broadcasterStatus, setBroadcasterStatus] = useState({}); + let getStatusIntervalId = null; + + + const getBroadcastStatus = async () => { + try { + const result = await fetchData(BROADCASTER); + const active = !!result.broadcaster; + + setBroadcasterStatus({ ...result, active }); + } catch(error) { + setBroadcasterStatus({ ...broadcasterStatus, message: error.message }); + }; + + + }; + + useEffect(() => { getBroadcastStatus(); }, []); + + + console.log("============",broadcasterStatus) + // getStatusIntervalId = setInterval(getBroadcastStatus, 15000); + return ( +
+ {JSON.stringify(broadcasterStatus)} +
+ ); +} diff --git a/web/pages/utils/apis.ts b/web/pages/utils/apis.ts new file mode 100644 index 000000000..30ffd327d --- /dev/null +++ b/web/pages/utils/apis.ts @@ -0,0 +1,62 @@ + + +const IS_DEV = true; +const ADMIN_USERNAME = 'admin'; +const ADMIN_STREAMKEY = 'abc123'; + +const API_LOCATION = 'http://localhost:8080/api/admin/'; + +// Current inbound broadcaster info +export const BROADCASTER = `${API_LOCATION}broadcaster`; + +// Disconnect inbound stream +export const DISCONNECT = `${API_LOCATION}disconnect`; + +// Change the current streaming key in memory +export const STREAMKEY_CHANGE = `${API_LOCATION}changekey`; + +// Current server config +export const SERVER_CONFIG = `${API_LOCATION}serverconfig`; + +// Get viewer count over time +export const VIEWERS_OVER_TIME = `${API_LOCATION}viewersOverTime`; + +// Get hardware stats +export const HARDWARE_STATS = `${API_LOCATION}hardwarestats`; + + + +// Current Stream status (no auth) +// use `admin/broadcaster` instead +// export const STREAM_STATUS = '/api/status'; + +export async function fetchData(url) { + const headers = new Headers(); + const encoded = btoa(`${ADMIN_USERNAME}:${ADMIN_STREAMKEY}`); + // headers.set('Authorization', `Basic ${encoded}`); + console.log({encoded}, `${ADMIN_USERNAME}:${ADMIN_STREAMKEY}`) + + + const response = await fetch(url, { + headers: { + 'Authorization': `Basic ${encoded}`, + 'Credentials': 'include', + }, + mode: 'no-cors', + }); + // waits until the request completes... + // console.log(response); + + if (!response.ok) { + const message = `An error has occured: ${response.status}`; + throw new Error(message); + } + + const json = await response.json(); + return json; +} + +// fetch error cases +// json.catch(error => { +// error.message; // 'An error has occurred: 404' +// }); From 12487011d20e3ac61c57582a482816f9117936c6 Mon Sep 17 00:00:00 2001 From: Gabe Kangas Date: Sat, 3 Oct 2020 23:07:37 -0700 Subject: [PATCH 02/14] Handle auth + cors --- web/pages/index2.tsx | 6 +++--- web/pages/utils/apis.ts | 38 ++++++++++++++++++++------------------ 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/web/pages/index2.tsx b/web/pages/index2.tsx index bb35f0dc3..6bc25988c 100644 --- a/web/pages/index2.tsx +++ b/web/pages/index2.tsx @@ -3,7 +3,7 @@ import { BROADCASTER, fetchData } from './utils/apis'; export default function Admin() { const [broadcasterStatus, setBroadcasterStatus] = useState({}); - let getStatusIntervalId = null; + const getStatusIntervalId = null; const getBroadcastStatus = async () => { @@ -12,7 +12,8 @@ export default function Admin() { const active = !!result.broadcaster; setBroadcasterStatus({ ...result, active }); - } catch(error) { + } catch (error) { + setBroadcasterStatus({ ...broadcasterStatus, message: error.message }); }; @@ -22,7 +23,6 @@ export default function Admin() { useEffect(() => { getBroadcastStatus(); }, []); - console.log("============",broadcasterStatus) // getStatusIntervalId = setInterval(getBroadcastStatus, 15000); return (
diff --git a/web/pages/utils/apis.ts b/web/pages/utils/apis.ts index 30ffd327d..90b478570 100644 --- a/web/pages/utils/apis.ts +++ b/web/pages/utils/apis.ts @@ -31,29 +31,31 @@ export const HARDWARE_STATS = `${API_LOCATION}hardwarestats`; // export const STREAM_STATUS = '/api/status'; export async function fetchData(url) { - const headers = new Headers(); const encoded = btoa(`${ADMIN_USERNAME}:${ADMIN_STREAMKEY}`); - // headers.set('Authorization', `Basic ${encoded}`); - console.log({encoded}, `${ADMIN_USERNAME}:${ADMIN_STREAMKEY}`) + try { + const response = await fetch(url, { + headers: { + 'Authorization': `Basic ${encoded}`, + }, + mode: 'cors', + credentials: 'include', + }); + // waits until the request completes... + // console.log(response); - const response = await fetch(url, { - headers: { - 'Authorization': `Basic ${encoded}`, - 'Credentials': 'include', - }, - mode: 'no-cors', - }); - // waits until the request completes... - // console.log(response); + if (!response.ok) { + console.log(response) + const message = `An error has occured: ${response.status}`; + throw new Error(message); + } - if (!response.ok) { - const message = `An error has occured: ${response.status}`; - throw new Error(message); + const json = await response.json(); + console.log(json) + return json; + } catch (error) { + console.log(error) } - - const json = await response.json(); - return json; } // fetch error cases From c7dc2a403045e0e3943c29c91c357092ef9c9c3f Mon Sep 17 00:00:00 2001 From: Ginger Wong Date: Wed, 7 Oct 2020 23:09:42 -0700 Subject: [PATCH 03/14] blah --- web/.env.development | 3 +++ web/.gitignore | 1 + web/pages/utils/apis.ts | 18 +++++++----------- 3 files changed, 11 insertions(+), 11 deletions(-) create mode 100644 web/.env.development diff --git a/web/.env.development b/web/.env.development new file mode 100644 index 000000000..90e649592 --- /dev/null +++ b/web/.env.development @@ -0,0 +1,3 @@ +NEXT_PUBLIC_ADMIN_USERNAME=admin +NEXT_PUBLIC_ADMIN_STREAMKEY=abc123 +NEXT_PUBLIC_API_HOST=http://localhost:8080/ \ No newline at end of file diff --git a/web/.gitignore b/web/.gitignore index 3c3629e64..f4088b7c6 100644 --- a/web/.gitignore +++ b/web/.gitignore @@ -1 +1,2 @@ node_modules +.env*.local diff --git a/web/pages/utils/apis.ts b/web/pages/utils/apis.ts index 90b478570..ee467044a 100644 --- a/web/pages/utils/apis.ts +++ b/web/pages/utils/apis.ts @@ -1,14 +1,14 @@ +/* eslint-disable prefer-destructuring */ +const ADMIN_USERNAME = process.env.ADMIN_USERNAME; +const ADMIN_STREAMKEY = process.env.ADMIN_STREAMKEY; +const NEXT_PUBLIC_API_HOST = process.env.NEXT_PUBLIC_API_HOST; - -const IS_DEV = true; -const ADMIN_USERNAME = 'admin'; -const ADMIN_STREAMKEY = 'abc123'; - -const API_LOCATION = 'http://localhost:8080/api/admin/'; +const API_LOCATION = `${NEXT_PUBLIC_API_HOST}api/admin/`; // Current inbound broadcaster info export const BROADCASTER = `${API_LOCATION}broadcaster`; + // Disconnect inbound stream export const DISCONNECT = `${API_LOCATION}disconnect`; @@ -56,9 +56,5 @@ export async function fetchData(url) { } catch (error) { console.log(error) } + return {}; } - -// fetch error cases -// json.catch(error => { -// error.message; // 'An error has occurred: 404' -// }); From c6c14bf216efd9f0d7a214b6eee4202d61d033c5 Mon Sep 17 00:00:00 2001 From: Ginger Wong Date: Thu, 8 Oct 2020 00:17:40 -0700 Subject: [PATCH 04/14] initial rough setup --- web/pages/components/broadcast-info.tsx | 15 ++++++++++ web/pages/components/hardware-info.tsx | 39 ++++++++++++++++++++++++ web/pages/components/viewer-info.tsx | 39 ++++++++++++++++++++++++ web/pages/home.tsx | 38 +++++++++++++++++++++++ web/pages/index2.tsx | 40 +++++++++++++++---------- web/pages/utils/apis.ts | 7 +++-- 6 files changed, 159 insertions(+), 19 deletions(-) create mode 100644 web/pages/components/broadcast-info.tsx create mode 100644 web/pages/components/hardware-info.tsx create mode 100644 web/pages/components/viewer-info.tsx create mode 100644 web/pages/home.tsx diff --git a/web/pages/components/broadcast-info.tsx b/web/pages/components/broadcast-info.tsx new file mode 100644 index 000000000..bf68c888d --- /dev/null +++ b/web/pages/components/broadcast-info.tsx @@ -0,0 +1,15 @@ +import React, { useState, useEffect } from 'react'; + + +export default function BroadcastInfo(props) { +const { remoteAddr, streamDetails, time } = props; + + return ( +
+

Broadcast Info

+

Remote Address: {remoteAddr}

+

Time: {(new Date(time)).toLocaleTimeString()}

+

Stream Details: {JSON.stringify(streamDetails)}

+
+ ); +} diff --git a/web/pages/components/hardware-info.tsx b/web/pages/components/hardware-info.tsx new file mode 100644 index 000000000..bfdd8ac67 --- /dev/null +++ b/web/pages/components/hardware-info.tsx @@ -0,0 +1,39 @@ +import React, { useState, useEffect } from 'react'; +import { HARDWARE_STATS, fetchData, FETCH_INTERVAL } from '../utils/apis'; + +export default function HardwareInfo() { + const [hardwareStatus, setHardwareStatus] = useState({}); + + const getHardwareStatus = async () => { + try { + const result = await fetchData(HARDWARE_STATS); + console.log("hardare result", result) + + setHardwareStatus({ ...result }); + + } catch (error) { + setHardwareStatus({ ...hardwareStatus, message: error.message }); + } + }; + + useEffect(() => { + let getStatusIntervalId = null; + + getHardwareStatus(); + getStatusIntervalId = setInterval(getHardwareStatus, FETCH_INTERVAL); + + // returned function will be called on component unmount + return () => { + clearInterval(getStatusIntervalId); + } + }, []); + + return ( +
+

Hardware Info

+
+ {JSON.stringify(hardwareStatus)} +
+
+ ); +} diff --git a/web/pages/components/viewer-info.tsx b/web/pages/components/viewer-info.tsx new file mode 100644 index 000000000..dfb034f83 --- /dev/null +++ b/web/pages/components/viewer-info.tsx @@ -0,0 +1,39 @@ +import React, { useState, useEffect } from 'react'; +import { VIEWERS_OVER_TIME, fetchData, FETCH_INTERVAL } from '../utils/apis'; + +export default function HardwareInfo() { + const [viewerInfo, setViewerInfo] = useState({}); + + const getInfo = async () => { + try { + const result = await fetchData(VIEWERS_OVER_TIME); + console.log("viewers result", result) + + setViewerInfo({ ...result }); + + } catch (error) { + setViewerInfo({ ...viewerInfo, message: error.message }); + } + }; + + useEffect(() => { + let getStatusIntervalId = null; + + getInfo(); + getStatusIntervalId = setInterval(getInfo, FETCH_INTERVAL); + + // returned function will be called on component unmount + return () => { + clearInterval(getStatusIntervalId); + } + }, []); + + return ( +
+

Viewers over time

+
+ {JSON.stringify(viewerInfo)} +
+
+ ); +} diff --git a/web/pages/home.tsx b/web/pages/home.tsx new file mode 100644 index 000000000..f30572156 --- /dev/null +++ b/web/pages/home.tsx @@ -0,0 +1,38 @@ +import React, { useState, useEffect } from 'react'; + +import BroadcastInfo from './components/broadcast-info'; +import HardwareInfo from './components/hardware-info'; +import ViewerInfo from './components/viewer-info'; + +export default function HomeView(props) { + const { broadcastActive, broadcaster, message } = props; + + const broadcastDetails = broadcastActive ? ( + <> + + + + + ) : null; + + const disconnectButton = broadcastActive ? : null; + + return ( +
+

+ Status: {broadcastActive ? 'on' : 'off'} +

+ +

Utilities

+ (these dont do anything yet) + {disconnectButton} + + + +
+
+ + {broadcastDetails} +
+ ); +} diff --git a/web/pages/index2.tsx b/web/pages/index2.tsx index 6bc25988c..acfd6f339 100644 --- a/web/pages/index2.tsx +++ b/web/pages/index2.tsx @@ -1,32 +1,40 @@ import React, { useState, useEffect } from 'react'; -import { BROADCASTER, fetchData } from './utils/apis'; +import { BROADCASTER, fetchData, FETCH_INTERVAL } from './utils/apis'; +import Main from './home'; export default function Admin() { const [broadcasterStatus, setBroadcasterStatus] = useState({}); - const getStatusIntervalId = null; + const [count, setCount] = useState(0); - - const getBroadcastStatus = async () => { + const getBroadcastStatus = async () => { try { const result = await fetchData(BROADCASTER); - const active = !!result.broadcaster; + const broadcastActive = !!result.broadcaster; + + console.log("====",{count, result}) + + setBroadcasterStatus({ ...result, broadcastActive }); + setCount(count => count + 1); - setBroadcasterStatus({ ...result, active }); } catch (error) { - setBroadcasterStatus({ ...broadcasterStatus, message: error.message }); - }; - - + } }; + + useEffect(() => { + let getStatusIntervalId = null; - useEffect(() => { getBroadcastStatus(); }, []); + getBroadcastStatus(); + getStatusIntervalId = setInterval(getBroadcastStatus, FETCH_INTERVAL); + + // returned function will be called on component unmount + return () => { + clearInterval(getStatusIntervalId); + } + }, []) - - // getStatusIntervalId = setInterval(getBroadcastStatus, 15000); + return ( -
- {JSON.stringify(broadcasterStatus)} -
+
); } diff --git a/web/pages/utils/apis.ts b/web/pages/utils/apis.ts index ee467044a..af85c89bc 100644 --- a/web/pages/utils/apis.ts +++ b/web/pages/utils/apis.ts @@ -1,14 +1,15 @@ /* eslint-disable prefer-destructuring */ -const ADMIN_USERNAME = process.env.ADMIN_USERNAME; -const ADMIN_STREAMKEY = process.env.ADMIN_STREAMKEY; +const ADMIN_USERNAME = process.env.NEXT_PUBLIC_ADMIN_USERNAME; +const ADMIN_STREAMKEY = process.env.NEXT_PUBLIC_ADMIN_STREAMKEY; const NEXT_PUBLIC_API_HOST = process.env.NEXT_PUBLIC_API_HOST; const API_LOCATION = `${NEXT_PUBLIC_API_HOST}api/admin/`; +export const FETCH_INTERVAL = 15000; + // Current inbound broadcaster info export const BROADCASTER = `${API_LOCATION}broadcaster`; - // Disconnect inbound stream export const DISCONNECT = `${API_LOCATION}disconnect`; From e554a2a87771c0bf948e3f0757d4d17ff972f2a9 Mon Sep 17 00:00:00 2001 From: Ginger Wong Date: Thu, 8 Oct 2020 00:26:24 -0700 Subject: [PATCH 05/14] add connectedclients endpoint --- web/pages/components/connected-clients.tsx | 39 ++++++++++++++++++++++ web/pages/home.tsx | 5 ++- web/pages/utils/apis.ts | 4 +++ 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 web/pages/components/connected-clients.tsx diff --git a/web/pages/components/connected-clients.tsx b/web/pages/components/connected-clients.tsx new file mode 100644 index 000000000..4261949e1 --- /dev/null +++ b/web/pages/components/connected-clients.tsx @@ -0,0 +1,39 @@ +import React, { useState, useEffect } from 'react'; +import { CONNECTED_CLIENTS, fetchData, FETCH_INTERVAL } from '../utils/apis'; + +export default function HardwareInfo() { + const [clients, setClients] = useState({}); + + const getInfo = async () => { + try { + const result = await fetchData(CONNECTED_CLIENTS); + console.log("viewers result", result) + + setClients({ ...result }); + + } catch (error) { + setClients({ ...clients, message: error.message }); + } + }; + + useEffect(() => { + let getStatusIntervalId = null; + + getInfo(); + getStatusIntervalId = setInterval(getInfo, FETCH_INTERVAL); + + // returned function will be called on component unmount + return () => { + clearInterval(getStatusIntervalId); + } + }, []); + + return ( +
+

Connected Clients

+
+ {JSON.stringify(clients)} +
+
+ ); +} diff --git a/web/pages/home.tsx b/web/pages/home.tsx index f30572156..530a9e721 100644 --- a/web/pages/home.tsx +++ b/web/pages/home.tsx @@ -3,6 +3,7 @@ import React, { useState, useEffect } from 'react'; import BroadcastInfo from './components/broadcast-info'; import HardwareInfo from './components/hardware-info'; import ViewerInfo from './components/viewer-info'; +import ConnectedClients from './components/connected-clients'; export default function HomeView(props) { const { broadcastActive, broadcaster, message } = props; @@ -12,6 +13,7 @@ export default function HomeView(props) { + ) : null; @@ -24,7 +26,8 @@ export default function HomeView(props) {

Utilities

- (these dont do anything yet) +

(these dont do anything yet)

+ {disconnectButton} diff --git a/web/pages/utils/apis.ts b/web/pages/utils/apis.ts index af85c89bc..891ad6b64 100644 --- a/web/pages/utils/apis.ts +++ b/web/pages/utils/apis.ts @@ -22,6 +22,10 @@ export const SERVER_CONFIG = `${API_LOCATION}serverconfig`; // Get viewer count over time export const VIEWERS_OVER_TIME = `${API_LOCATION}viewersOverTime`; +// Get currently connected clients +export const CONNECTED_CLIENTS = `${API_LOCATION}clients`; + + // Get hardware stats export const HARDWARE_STATS = `${API_LOCATION}hardwarestats`; From 456d422bd713664accc4a8bd320cb9473003e1cc Mon Sep 17 00:00:00 2001 From: Ginger Wong Date: Sat, 10 Oct 2020 17:52:13 -0700 Subject: [PATCH 06/14] add victory graphing lib --- web/.gitignore | 2 + web/package-lock.json | 434 ++++++++++++++++++++++++++++++++++++++++++ web/package.json | 3 +- 3 files changed, 438 insertions(+), 1 deletion(-) diff --git a/web/.gitignore b/web/.gitignore index f4088b7c6..358a850a1 100644 --- a/web/.gitignore +++ b/web/.gitignore @@ -1,2 +1,4 @@ node_modules .env*.local + +.next \ No newline at end of file diff --git a/web/package-lock.json b/web/package-lock.json index 0df8f9458..1bfd1e339 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -2904,6 +2904,89 @@ "type": "^1.0.1" } }, + "d3-array": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", + "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==" + }, + "d3-collection": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz", + "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==" + }, + "d3-color": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz", + "integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==" + }, + "d3-ease": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz", + "integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ==" + }, + "d3-format": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz", + "integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==" + }, + "d3-interpolate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz", + "integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==", + "requires": { + "d3-color": "1" + } + }, + "d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==" + }, + "d3-scale": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-1.0.7.tgz", + "integrity": "sha512-KvU92czp2/qse5tUfGms6Kjig0AhHOwkzXG0+PqIJB3ke0WUv088AHMZI0OssO9NCkXt4RP8yju9rpH8aGB7Lw==", + "requires": { + "d3-array": "^1.2.0", + "d3-collection": "1", + "d3-color": "1", + "d3-format": "1", + "d3-interpolate": "1", + "d3-time": "1", + "d3-time-format": "2" + } + }, + "d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "requires": { + "d3-path": "1" + } + }, + "d3-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz", + "integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==" + }, + "d3-time-format": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz", + "integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==", + "requires": { + "d3-time": "1" + } + }, + "d3-timer": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz", + "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==" + }, + "d3-voronoi": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz", + "integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==" + }, "damerau-levenshtein": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz", @@ -2992,6 +3075,19 @@ } } }, + "delaunator": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-4.0.1.tgz", + "integrity": "sha512-WNPWi1IRKZfCt/qIDMfERkDp93+iZEmOxN2yy4Jg+Xhv8SLk2UTqqbe1sfiipn0and9QrE914/ihdx82Y/Giag==" + }, + "delaunay-find": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/delaunay-find/-/delaunay-find-0.0.5.tgz", + "integrity": "sha512-7yAJ/wmKWj3SgqjtkGqT/RCwI0HWAo5YnHMoF5nYXD8cdci+YSo23iPmgrZUNOpDxRWN91PqxUvMMr2lKpjr+w==", + "requires": { + "delaunator": "^4.0.0" + } + }, "des.js": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", @@ -6354,6 +6450,11 @@ "scheduler": "^0.19.1" } }, + "react-fast-compare": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", + "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==" + }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -7965,6 +8066,339 @@ "spdx-expression-parse": "^3.0.0" } }, + "victory": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory/-/victory-35.1.1.tgz", + "integrity": "sha512-PJYPP71dW73qPiemlYBtRjWuw0wmyk8rfbmeUyrzrUG/xwfeO52N96P7MXcV+dBXR4BzLy0G5D0bvGksBFfVWw==", + "requires": { + "victory-area": "^35.1.1", + "victory-axis": "^35.1.1", + "victory-bar": "^35.1.1", + "victory-box-plot": "^35.1.1", + "victory-brush-container": "^35.1.1", + "victory-brush-line": "^35.1.1", + "victory-candlestick": "^35.1.1", + "victory-chart": "^35.1.1", + "victory-core": "^35.1.1", + "victory-create-container": "^35.1.1", + "victory-cursor-container": "^35.1.1", + "victory-errorbar": "^35.1.1", + "victory-group": "^35.1.1", + "victory-histogram": "^35.1.1", + "victory-legend": "^35.1.1", + "victory-line": "^35.1.1", + "victory-pie": "^35.1.1", + "victory-polar-axis": "^35.1.1", + "victory-scatter": "^35.1.1", + "victory-selection-container": "^35.1.1", + "victory-shared-events": "^35.1.1", + "victory-stack": "^35.1.1", + "victory-tooltip": "^35.1.1", + "victory-voronoi": "^35.1.1", + "victory-voronoi-container": "^35.1.1", + "victory-zoom-container": "^35.1.1" + } + }, + "victory-area": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-area/-/victory-area-35.1.1.tgz", + "integrity": "sha512-Ghh4x7GEhR8LQo1duy4mKzCMVpxOzlYf2H8Wwvh3TwOMitwbfBZ91P9bYOv3KEsVxfzmbuGM4fKfkJEFcwXQiA==", + "requires": { + "d3-shape": "^1.2.0", + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "victory-core": "^35.1.1" + } + }, + "victory-axis": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-axis/-/victory-axis-35.1.1.tgz", + "integrity": "sha512-HQkGTHKgk32vjPrGG/1LNvodnywnI7fMoNHwCvJVXy+C+2N3UKB828zvdkuDtq9Cc4GSPBWsMzPJxyi5kRjV6g==", + "requires": { + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "victory-core": "^35.1.1" + } + }, + "victory-bar": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-bar/-/victory-bar-35.1.1.tgz", + "integrity": "sha512-VuY286MhccpqroedPOvjy7zJbZxtHsJ/VloywrOWjjcWIGRuh+Ln3zlT/8aJC1Vs4X9+WHwAdUKVR1FTufKjkQ==", + "requires": { + "d3-shape": "^1.2.0", + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "victory-core": "^35.1.1" + } + }, + "victory-box-plot": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-box-plot/-/victory-box-plot-35.1.1.tgz", + "integrity": "sha512-B9H9G5GmQvHM6Ydy+9vTaNNh+7DtNnUe5I7DNtJt9Ou8RWckI2F3sX1pudMLRy1LHV3d1fnxxBuOADxCTo6BcA==", + "requires": { + "d3-array": "^1.2.0", + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "victory-core": "^35.1.1" + } + }, + "victory-brush-container": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-brush-container/-/victory-brush-container-35.1.1.tgz", + "integrity": "sha512-1e1Q2CJn2LMGmAwdtvDbKI6XicqLw8YSNLRcjeCBmxtMotY8yHK91G/7Wr5OwiwCkjzFDf3P4XRprHTK1t6hNg==", + "requires": { + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "react-fast-compare": "^2.0.0", + "victory-core": "^35.1.1" + } + }, + "victory-brush-line": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-brush-line/-/victory-brush-line-35.1.1.tgz", + "integrity": "sha512-kNCPUxzXij0fPkhfMkJDDHQ8N820suY5mC2Eh2g+lcwOdA3ha3w9UNxMwDNlbXOLqJs5Bw1QweWnRfIBbWNfZA==", + "requires": { + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "react-fast-compare": "^2.0.0", + "victory-core": "^35.1.1" + } + }, + "victory-candlestick": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-candlestick/-/victory-candlestick-35.1.1.tgz", + "integrity": "sha512-4h/4+d9kHCPinK45HWgpO6+k0bYzHBWDoW0rZILCGQYCNSjy4UDHF0UiP6X1QLADrV7d47ZnK83lruVcQjgxKw==", + "requires": { + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "victory-core": "^35.1.1" + } + }, + "victory-chart": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-chart/-/victory-chart-35.1.1.tgz", + "integrity": "sha512-B8dixl5RmIxmh0CPVBv/0cSjZ31FNvQmFX9t352Df4VQ5fU23hvmqCUASE2QboIcIeAiH+Qj0NKycu+lr0GgjA==", + "requires": { + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "react-fast-compare": "^2.0.0", + "victory-axis": "^35.1.1", + "victory-core": "^35.1.1", + "victory-polar-axis": "^35.1.1", + "victory-shared-events": "^35.1.1" + } + }, + "victory-core": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-core/-/victory-core-35.1.1.tgz", + "integrity": "sha512-DnWwTLPOpVLgnz52h4SY1CBUxkdxfX14cDPC4Ly8rWY7I3OXuEhzE3Wx/SYQO9vk7oQ7zp8ukWRVWpVpcEZzug==", + "requires": { + "d3-ease": "^1.0.0", + "d3-interpolate": "^1.1.1", + "d3-scale": "^1.0.0", + "d3-shape": "^1.2.0", + "d3-timer": "^1.0.0", + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "react-fast-compare": "^2.0.0" + } + }, + "victory-create-container": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-create-container/-/victory-create-container-35.1.1.tgz", + "integrity": "sha512-QDnCXKL0JovglmT7Fs7rC+GiPgXcJWlXC8LDWpo0kWXD0OP7jNwkCmO78/QU4tlcAWtVY/CNU+rBMxwDTS6/WQ==", + "requires": { + "lodash": "^4.17.19", + "victory-brush-container": "^35.1.1", + "victory-core": "^35.1.1", + "victory-cursor-container": "^35.1.1", + "victory-selection-container": "^35.1.1", + "victory-voronoi-container": "^35.1.1", + "victory-zoom-container": "^35.1.1" + } + }, + "victory-cursor-container": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-cursor-container/-/victory-cursor-container-35.1.1.tgz", + "integrity": "sha512-wD4N7k+YbHDUJleTgYqvYheN1c/qYlcZ44pXw8BKKqywtZixU8Pm9Tioo6L5e0+nSiGyJDixdvMpt2C5hGHNDw==", + "requires": { + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "victory-core": "^35.1.1" + } + }, + "victory-errorbar": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-errorbar/-/victory-errorbar-35.1.1.tgz", + "integrity": "sha512-Oz8Fwsg0kDJETnH2B8asbTmOy3uvCgIsF80rY4NKqoGYcfaqY8xhmbxz+ipMyL826+mg3WmTnqVpbdXm3Y3oXw==", + "requires": { + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "victory-core": "^35.1.1" + } + }, + "victory-group": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-group/-/victory-group-35.1.1.tgz", + "integrity": "sha512-OpSAXZ7InMXWT9AEo5UA/QYaD8i9F7pdHqvcSDckoEJPwZ6Sr7deE9LpfVo3KeK6PjzjQBZdrBPggSZwcvl0Zw==", + "requires": { + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "react-fast-compare": "^2.0.0", + "victory-core": "^35.1.1", + "victory-shared-events": "^35.1.1" + } + }, + "victory-histogram": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-histogram/-/victory-histogram-35.1.1.tgz", + "integrity": "sha512-S/CGu7nIlN8kSQMNSMRWw9Nr4x/Z9W5giix4nxfj8M1tu0epNsRED4Jav2NUn7S3z+f2N76uJo80zVk894JK+A==", + "requires": { + "d3-array": "^2.4.0", + "d3-scale": "^1.0.0", + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "react-fast-compare": "^2.0.0", + "victory-bar": "^35.1.1", + "victory-core": "^35.1.1" + }, + "dependencies": { + "d3-array": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.8.0.tgz", + "integrity": "sha512-6V272gsOeg7+9pTW1jSYOR1QE37g95I3my1hBmY+vOUNHRrk9yt4OTz/gK7PMkVAVDrYYq4mq3grTiZ8iJdNIw==" + } + } + }, + "victory-legend": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-legend/-/victory-legend-35.1.1.tgz", + "integrity": "sha512-RibASpnHin6TAXRhgngEk71Y++Wh+ikRH8nV2hygT+WtTolRj6RsAA43jQwTv4cDqt3v2k+Ddoh4eXpJoH3R2Q==", + "requires": { + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "victory-core": "^35.1.1" + } + }, + "victory-line": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-line/-/victory-line-35.1.1.tgz", + "integrity": "sha512-PAY6Q8SN0p4vBiMvBUXVNb3FrZ7BWaN3/8/pWUKKobTVSiKaJmaDXR9u9EDn7yErjwxsFqJQ8+918pfkWvWWNg==", + "requires": { + "d3-shape": "^1.2.0", + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "victory-core": "^35.1.1" + } + }, + "victory-pie": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-pie/-/victory-pie-35.1.1.tgz", + "integrity": "sha512-PFzceL0LPIK30Flz3OrEB7vSCHm5oaQInvvufuUsTUPHxBjq0QDqukV5zHCz0OfdFZ+KzqCTdwD95EFyC1yrYA==", + "requires": { + "d3-shape": "^1.0.0", + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "victory-core": "^35.1.1" + } + }, + "victory-polar-axis": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-polar-axis/-/victory-polar-axis-35.1.1.tgz", + "integrity": "sha512-Y6iFqfkkI3Be4ltg+3AsmXUkk9uDQ+IU6XQWzZ0PZGGEt1ftiRX5GS2tfTQcV//qsannX6t2xKBc0iquPI3+Kw==", + "requires": { + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "victory-core": "^35.1.1" + } + }, + "victory-scatter": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-scatter/-/victory-scatter-35.1.1.tgz", + "integrity": "sha512-IgJNQHXx7lUoFnUoMNeCatBso+sIdx6/v0Hx94GeP3X6UmGPzBnM9JlyjVQjyJuiEoWQ0MtFhqidy+CSvn4pJg==", + "requires": { + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "victory-core": "^35.1.1" + } + }, + "victory-selection-container": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-selection-container/-/victory-selection-container-35.1.1.tgz", + "integrity": "sha512-lait103pBL1h9Jv65OiR8xfXhoQ79KpjWsgx0fZQGi+HcvzaKTAv9XGAMqB6GT3PkXFEqrz9K+0cAaRHd8SPvQ==", + "requires": { + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "victory-core": "^35.1.1" + } + }, + "victory-shared-events": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-shared-events/-/victory-shared-events-35.1.1.tgz", + "integrity": "sha512-h4qMyZuvTlZAq/UuP3R6ETCLYSmggzU01ZuAbxEqygt+XQ04yG2QJmf8stKxvS1ktYFIXVdrJr/bJjTAIZQ0XQ==", + "requires": { + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "react-fast-compare": "^2.0.0", + "victory-core": "^35.1.1" + } + }, + "victory-stack": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-stack/-/victory-stack-35.1.1.tgz", + "integrity": "sha512-SKXd6YG97CH9KsQB+akhc2jos+6vjGmyJkaHuTXuqGL9TrGtTM1WA784LAOFbNourk/VRTf1TJOz0EtzO2orIw==", + "requires": { + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "react-fast-compare": "^2.0.0", + "victory-core": "^35.1.1", + "victory-shared-events": "^35.1.1" + } + }, + "victory-tooltip": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-tooltip/-/victory-tooltip-35.1.1.tgz", + "integrity": "sha512-2ZMecFgL6lQ2exzNGBmnUia967plHRWAinUYaRMSY4R3+FgOjCLkdVu1XBf/y6EBn+urIw3VK4yS8pn9ESjSOQ==", + "requires": { + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "victory-core": "^35.1.1" + } + }, + "victory-voronoi": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-voronoi/-/victory-voronoi-35.1.1.tgz", + "integrity": "sha512-b8Ec7a/253tgpC+KH2CdvAl+DubSAXWYyd30Bd6T1+oPx+KmRdB76uEmnqUHXzBCEHnkjazfOPb2nLItCoOR9g==", + "requires": { + "d3-voronoi": "^1.1.2", + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "victory-core": "^35.1.1" + } + }, + "victory-voronoi-container": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-voronoi-container/-/victory-voronoi-container-35.1.1.tgz", + "integrity": "sha512-AcCOhGMt9WYGDQtGIfbHhabdTmj92Uwr0fyfg+StrZk6AB/KgJproRcKQ91jLQExQkaoqdB9DP83LYGjWnk0zg==", + "requires": { + "delaunay-find": "0.0.5", + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "react-fast-compare": "^2.0.0", + "victory-core": "^35.1.1", + "victory-tooltip": "^35.1.1" + } + }, + "victory-zoom-container": { + "version": "35.1.1", + "resolved": "https://registry.npmjs.org/victory-zoom-container/-/victory-zoom-container-35.1.1.tgz", + "integrity": "sha512-U0sKD56muX1ZK/mBWYjdRUDtrsIRBGHC9MIpNL0Ju6sIoqH//uyBFoO617xf5VMO8iUYywjXEqzXb+60XK41TQ==", + "requires": { + "lodash": "^4.17.19", + "prop-types": "^15.5.8", + "victory-core": "^35.1.1" + } + }, "vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", diff --git a/web/package.json b/web/package.json index 093050dce..5baa52717 100644 --- a/web/package.json +++ b/web/package.json @@ -13,7 +13,8 @@ "next": "9.5.3", "react": "16.13.1", "react-dom": "16.13.1", - "sass": "^1.26.11" + "sass": "^1.26.11", + "victory": "^35.1.1" }, "devDependencies": { "@types/node": "^14.11.2", From e53ea1d6cf3bbd838e77862a71e8e7302b9db678 Mon Sep 17 00:00:00 2001 From: Ginger Wong Date: Sat, 10 Oct 2020 18:25:21 -0700 Subject: [PATCH 07/14] add proptypes --- web/package.json | 2 + web/pages/home.tsx | 10 +- web/yarn.lock | 404 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 409 insertions(+), 7 deletions(-) diff --git a/web/package.json b/web/package.json index 5baa52717..a6f6052c6 100644 --- a/web/package.json +++ b/web/package.json @@ -11,6 +11,7 @@ "@ant-design/icons": "^4.2.2", "antd": "^4.6.6", "next": "9.5.3", + "prop-types": "^15.7.2", "react": "16.13.1", "react-dom": "16.13.1", "sass": "^1.26.11", @@ -18,6 +19,7 @@ }, "devDependencies": { "@types/node": "^14.11.2", + "@types/prop-types": "^15.7.3", "@types/react": "^16.9.49", "@typescript-eslint/eslint-plugin": "^4.3.0", "@typescript-eslint/parser": "^4.3.0", diff --git a/web/pages/home.tsx b/web/pages/home.tsx index 530a9e721..cd63d9fc4 100644 --- a/web/pages/home.tsx +++ b/web/pages/home.tsx @@ -8,7 +8,7 @@ import ConnectedClients from './components/connected-clients'; export default function HomeView(props) { const { broadcastActive, broadcaster, message } = props; - const broadcastDetails = broadcastActive ? ( + const broadcastDetails = broadcastActive ? ( <> @@ -18,16 +18,16 @@ export default function HomeView(props) { ) : null; const disconnectButton = broadcastActive ? : null; - + return ( -
+

Status: {broadcastActive ? 'on' : 'off'}

Utilities

(these dont do anything yet)

- + {disconnectButton} @@ -35,7 +35,7 @@ export default function HomeView(props) {

- {broadcastDetails} + {broadcastDetails}
); } diff --git a/web/yarn.lock b/web/yarn.lock index d6939400c..46cf3dbff 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -1147,7 +1147,7 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.11.2.tgz#2de1ed6670439387da1c9f549a2ade2b0a799256" integrity sha512-jiE3QIxJ8JLNcb1Ps6rDbysDhN4xa8DJJvuC9prr6w+1tIh+QAbYyNF3tyiZNLDBIuBCf4KEcV2UvQm/V60xfA== -"@types/prop-types@*": +"@types/prop-types@*", "@types/prop-types@^15.7.3": version "15.7.3" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== @@ -2443,6 +2443,90 @@ cyclist@^1.0.1: resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= +d3-array@^1.2.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f" + integrity sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw== + +d3-array@^2.4.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-2.8.0.tgz#f76e10ad47f1f4f75f33db5fc322eb9ffde5ef23" + integrity sha512-6V272gsOeg7+9pTW1jSYOR1QE37g95I3my1hBmY+vOUNHRrk9yt4OTz/gK7PMkVAVDrYYq4mq3grTiZ8iJdNIw== + +d3-collection@1: + version "1.0.7" + resolved "https://registry.yarnpkg.com/d3-collection/-/d3-collection-1.0.7.tgz#349bd2aa9977db071091c13144d5e4f16b5b310e" + integrity sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A== + +d3-color@1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-1.4.1.tgz#c52002bf8846ada4424d55d97982fef26eb3bc8a" + integrity sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q== + +d3-ease@^1.0.0: + version "1.0.7" + resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-1.0.7.tgz#9a834890ef8b8ae8c558b2fe55bd57f5993b85e2" + integrity sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ== + +d3-format@1: + version "1.4.5" + resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.4.5.tgz#374f2ba1320e3717eb74a9356c67daee17a7edb4" + integrity sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ== + +d3-interpolate@1, d3-interpolate@^1.1.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-1.4.0.tgz#526e79e2d80daa383f9e0c1c1c7dcc0f0583e987" + integrity sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA== + dependencies: + d3-color "1" + +d3-path@1: + version "1.0.9" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.9.tgz#48c050bb1fe8c262493a8caf5524e3e9591701cf" + integrity sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg== + +d3-scale@^1.0.0: + version "1.0.7" + resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-1.0.7.tgz#fa90324b3ea8a776422bd0472afab0b252a0945d" + integrity sha512-KvU92czp2/qse5tUfGms6Kjig0AhHOwkzXG0+PqIJB3ke0WUv088AHMZI0OssO9NCkXt4RP8yju9rpH8aGB7Lw== + dependencies: + d3-array "^1.2.0" + d3-collection "1" + d3-color "1" + d3-format "1" + d3-interpolate "1" + d3-time "1" + d3-time-format "2" + +d3-shape@^1.0.0, d3-shape@^1.2.0: + version "1.3.7" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.3.7.tgz#df63801be07bc986bc54f63789b4fe502992b5d7" + integrity sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw== + dependencies: + d3-path "1" + +d3-time-format@2: + version "2.3.0" + resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-2.3.0.tgz#107bdc028667788a8924ba040faf1fbccd5a7850" + integrity sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ== + dependencies: + d3-time "1" + +d3-time@1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.1.0.tgz#b1e19d307dae9c900b7e5b25ffc5dcc249a8a0f1" + integrity sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA== + +d3-timer@^1.0.0: + version "1.0.10" + resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-1.0.10.tgz#dfe76b8a91748831b13b6d9c793ffbd508dd9de5" + integrity sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw== + +d3-voronoi@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/d3-voronoi/-/d3-voronoi-1.1.4.tgz#dd3c78d7653d2bb359284ae478645d95944c8297" + integrity sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg== + d@1, d@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" @@ -2526,6 +2610,18 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" +delaunator@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-4.0.1.tgz#3d779687f57919a7a418f8ab947d3bddb6846957" + integrity sha512-WNPWi1IRKZfCt/qIDMfERkDp93+iZEmOxN2yy4Jg+Xhv8SLk2UTqqbe1sfiipn0and9QrE914/ihdx82Y/Giag== + +delaunay-find@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/delaunay-find/-/delaunay-find-0.0.5.tgz#5fb37e6509da934881b4b16c08898ac89862c097" + integrity sha512-7yAJ/wmKWj3SgqjtkGqT/RCwI0HWAo5YnHMoF5nYXD8cdci+YSo23iPmgrZUNOpDxRWN91PqxUvMMr2lKpjr+w== + dependencies: + delaunator "^4.0.0" + des.js@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" @@ -4873,7 +4969,7 @@ promise-inflight@^1.0.1: resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= -prop-types@15.7.2, prop-types@^15.5.10, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@15.7.2, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -5337,6 +5433,11 @@ react-dom@16.13.1: prop-types "^15.6.2" scheduler "^0.19.1" +react-fast-compare@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9" + integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw== + react-is@16.13.1, react-is@^16.12.0, react-is@^16.7.0, react-is@^16.8.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" @@ -6430,6 +6531,305 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" +victory-area@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-area/-/victory-area-35.2.0.tgz#6e47a97d627e66da3609e08068802026aba29e21" + integrity sha512-07QHwpZtyLmJoUJjX3HNSE9fDHV9Z2vExEze4HO9MjBA9+zx7d5OgCsYJlPafU2Y1FFgIgLmgYTBW4OO9e/yIQ== + dependencies: + d3-shape "^1.2.0" + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.2.0" + +victory-axis@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-axis/-/victory-axis-35.2.0.tgz#ae747d19c38dd30f2e80296cb11b944f6e99707c" + integrity sha512-6OlAMGtbBwkRcx8YyPqMjjS7JfoYWWZ2OPM2Zxm04dCy94LO2eZqC31IV7SHW3A0h/+j33JDnkLrbuaAWOf+hw== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.2.0" + +victory-bar@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-bar/-/victory-bar-35.2.0.tgz#2cfde9d7f390cce24ddf82106d1220e0c81a9cce" + integrity sha512-QyLPhrL/8pFFGX04aq5hUsaIFcB9OOD5b+9PujpobHZjLICHlkkY25SBV1bKTBkzblxZF+kldNHS60EovCNNhw== + dependencies: + d3-shape "^1.2.0" + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.2.0" + +victory-box-plot@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-box-plot/-/victory-box-plot-35.2.0.tgz#8691b5fb5449006532c6b887769c0f5678f0f60c" + integrity sha512-6HWVo/7QTnYiN6MExis9mmiCb45HRAfidW31CBQ8jCf6k//DOPYpKBPNJfChosdr2f5DUS42bQXlvraCdmDSRA== + dependencies: + d3-array "^1.2.0" + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.2.0" + +victory-brush-container@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-brush-container/-/victory-brush-container-35.2.0.tgz#cec3994a332490e1d6e9c756e5a1d71a93234d9c" + integrity sha512-KgfdxiP5/ka18uu+gvgDizTMa+RknKforIX6sE9Kx++BvX3QZZvS7N6wmiot7jud4Pyo90rtxJoRG4NigIxVWA== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + react-fast-compare "^2.0.0" + victory-core "^35.2.0" + +victory-brush-line@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-brush-line/-/victory-brush-line-35.2.0.tgz#2657057eb8a48ed2ad847f86f2a24a4fe9fceeab" + integrity sha512-9NAszFUobuOE3cLIdXHQJJ5V41INo5iMJQg5lbhJRI83QQsw4gNIYpRPr3CBhjTaPBDvfVxwEubUBfwWAE/jWg== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + react-fast-compare "^2.0.0" + victory-core "^35.2.0" + +victory-candlestick@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-candlestick/-/victory-candlestick-35.2.0.tgz#ca6cafd24b4ee9784cbef56a14eedfda225f9581" + integrity sha512-lYia+78umewrD5Rcl+YpBHweoyAf/OAWaCP164BWOCDrp8WQ7a4h6xD6FCk0btAvi8sC8WUsPeA5tIe+YtnFCQ== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.2.0" + +victory-chart@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-chart/-/victory-chart-35.2.0.tgz#42deb6988c79ff2d3a1bd3c2c869666bb58c399b" + integrity sha512-Jn/hlSEJh6pOlSyBvVzoQti5gWilKmWR9qew2HsO7NyZSwkxUI41I9kh+0YlzbScT4ANIq2bJxgaQrH9qeGBFg== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + react-fast-compare "^2.0.0" + victory-axis "^35.2.0" + victory-core "^35.2.0" + victory-polar-axis "^35.2.0" + victory-shared-events "^35.2.0" + +victory-core@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-core/-/victory-core-35.2.0.tgz#65b00995648fd149f0ef3e2121f441dfd775dc9e" + integrity sha512-ha4j1vfWKEJVhN1NT61Aoq1WJbpLWG4RSHuuDaTyRkdp2Zz2mYEo+F0UAYxbcXhcdE3fik4ZZULiv8ve64fIYw== + dependencies: + d3-ease "^1.0.0" + d3-interpolate "^1.1.1" + d3-scale "^1.0.0" + d3-shape "^1.2.0" + d3-timer "^1.0.0" + lodash "^4.17.19" + prop-types "^15.5.8" + react-fast-compare "^2.0.0" + +victory-create-container@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-create-container/-/victory-create-container-35.2.0.tgz#dd2cec040fa7189ec59cff9114df6b97c3332609" + integrity sha512-krxZpJKSwMDc6sfAeSRkjF6tdDa7P12LFOCA9unW33Vr2WsQQs8s6+ol+fch8TFB8i5Q6yDISRj69sxzQztwzA== + dependencies: + lodash "^4.17.19" + victory-brush-container "^35.2.0" + victory-core "^35.2.0" + victory-cursor-container "^35.2.0" + victory-selection-container "^35.2.0" + victory-voronoi-container "^35.2.0" + victory-zoom-container "^35.2.0" + +victory-cursor-container@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-cursor-container/-/victory-cursor-container-35.2.0.tgz#b5f04357c991253cfe894ffa89e2be200b8a17f2" + integrity sha512-VIl1h15Js2Mvkd1YOAgiFKuOxV+Lsn+GcbWS3gPuDDZlTVL82+n/nmcBXf+t6v41tZz9GUfcVphp8MCAT/tiog== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.2.0" + +victory-errorbar@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-errorbar/-/victory-errorbar-35.2.0.tgz#bd5897628d042fdada078d8379e009803dad41ff" + integrity sha512-JamxvyjxHwcbJU7eV3HnGbi1SdhvoOKC3zadJr/e/jItMtJrMQWIdErpj/XcL9ScQkLBEq8Plzya3YQo7tSvKA== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.2.0" + +victory-group@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-group/-/victory-group-35.2.0.tgz#f314b50f2a617c7248708ad3cd0bd10a3f7d083a" + integrity sha512-crv7to0RkJktrRk8fNoPuXsEYCplQk9Q+BV0AxLTEnPkRyxgUCjHgEgqQ8wqCXfPLYtyjUUteJhGDjinm3e4FQ== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + react-fast-compare "^2.0.0" + victory-core "^35.2.0" + victory-shared-events "^35.2.0" + +victory-histogram@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-histogram/-/victory-histogram-35.2.0.tgz#be97f87b3fa7ddeafe6ef1e6602f1703b28fa63e" + integrity sha512-Rl7BO8FVtOW7dbgtcDc1iNbZWRKBpACtauIgOAPeFwRfohTPOGzbFTiayo/5eqm7wHR4NfB94MY63eOD2vozqQ== + dependencies: + d3-array "^2.4.0" + d3-scale "^1.0.0" + lodash "^4.17.19" + prop-types "^15.5.8" + react-fast-compare "^2.0.0" + victory-bar "^35.2.0" + victory-core "^35.2.0" + +victory-legend@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-legend/-/victory-legend-35.2.0.tgz#741fed1db9d1e93c29094c23dd6d2b0381f63915" + integrity sha512-PiAD3pMg8E7scRRfSHRxgXjWS1xFY0t3BXLYEN4NzxDIyYshHZTWAfn5kOnEDuugd7vovEsog+kyMyXhy/miIg== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.2.0" + +victory-line@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-line/-/victory-line-35.2.0.tgz#99edb0d78db4335fb2d7ffb9bd1a6007edad3e22" + integrity sha512-Rx51MW46yJfOvGpj71FfYAPOBdSUPQYTpSFdKUEmtFoZwu84dUtHiAbmISk8d8vQTYJDDsGFxgmi2XantR13RA== + dependencies: + d3-shape "^1.2.0" + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.2.0" + +victory-pie@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-pie/-/victory-pie-35.2.0.tgz#728ea5b8b35fc7a87c69681c8863a370b3c495c4" + integrity sha512-nt9iRb2GGcKE46bmG8P5LbX+ouYQJi4/e85rfGjUtEVusz2jo2mQ17eeQpZJAJi9R7WlUtM33MxnaqtnZwHYjA== + dependencies: + d3-shape "^1.0.0" + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.2.0" + +victory-polar-axis@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-polar-axis/-/victory-polar-axis-35.2.0.tgz#cdd3237bfdcd2ca82d7beff1d2eb75c3c25a302d" + integrity sha512-kZJz1ecEN90ycvEWt3scYlsZUAVddpy/nE0MVok/ALI6LU9cJ1cGBvwTxhtXSjs8Yfcl7G3l880MhWIqG5JdyQ== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.2.0" + +victory-scatter@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-scatter/-/victory-scatter-35.2.0.tgz#bb691587c278e2890b43063290292bb0858c18c2" + integrity sha512-C/yjqT5z2ymWu0vPUZFbiEchLSbwCoo/Fwv6VHfia/sI05W1huZ9+5voUstMe9SqLnT/31XF+lUb+xIffcE6qg== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.2.0" + +victory-selection-container@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-selection-container/-/victory-selection-container-35.2.0.tgz#2ad22f05bce7e740c333b65e75f3255b3e2fd61e" + integrity sha512-mHvTdGxClA2m0HBIleg578GGcsRp7qLL8Rj2n8/iFetzLf9GLE9CtF+a1HKd8yLAeij6XmCNq8MIvO4ERg725g== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.2.0" + +victory-shared-events@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-shared-events/-/victory-shared-events-35.2.0.tgz#345e11acf3cd91a1ea98a406072519161486e97c" + integrity sha512-M+dvtCwK/YsnZ6ruKjrir0WfK0n5b63tLer3GwdiEdMyaWgn4hEDhafpH5PYagyG00ujSqadgf3DMRQoimv+dw== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + react-fast-compare "^2.0.0" + victory-core "^35.2.0" + +victory-stack@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-stack/-/victory-stack-35.2.0.tgz#b2005101b85edfb62af1692f6d9173bd80f41b5c" + integrity sha512-ofNCYpTj5Qq8ruYLFo46aQ4WyNZ514wqZUytGhs9+muJTClCjmnP4f6jfbsghZbPPucv0fGwABoiXcYIc+fJ5Q== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + react-fast-compare "^2.0.0" + victory-core "^35.2.0" + victory-shared-events "^35.2.0" + +victory-tooltip@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-tooltip/-/victory-tooltip-35.2.0.tgz#56189f6d61ba4262405e32a84a2ee75d98826db2" + integrity sha512-w6M2g+c0ZFfKM80Cife/9kCOd3xiXSaSCjdokp2GRBA8zD9CkbiCAGYLsF+CQBSoeZpMCyzC6bsiEtzb4SD48g== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.2.0" + +victory-voronoi-container@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-voronoi-container/-/victory-voronoi-container-35.2.0.tgz#38155b9c97836eb1785ac2720e9c3204b37d33ac" + integrity sha512-mevciZwcVuQ9k4PqTSz/3hSF+XyHR1DbYoZsAZJlocsezncYtdxKYbw7MOraubio/H5wCgsICi/llmxiPFmPHg== + dependencies: + delaunay-find "0.0.5" + lodash "^4.17.19" + prop-types "^15.5.8" + react-fast-compare "^2.0.0" + victory-core "^35.2.0" + victory-tooltip "^35.2.0" + +victory-voronoi@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-voronoi/-/victory-voronoi-35.2.0.tgz#e6d7341566dff915ac597baa660961f8f52b469e" + integrity sha512-TJ6t2Bxl5wu451igdJ/vIKddBIHxSJgGbuGybYgj0CTjl4KH9U16Gx8ILILm2bW07/Am1PFWQpjFjK+3Gn5NdA== + dependencies: + d3-voronoi "^1.1.2" + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.2.0" + +victory-zoom-container@^35.2.0: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory-zoom-container/-/victory-zoom-container-35.2.0.tgz#94e869ce6e6eca22816e1575402c7e304af39a6f" + integrity sha512-cmR5IAfL92+ESYk6klwxINlFAQ5kO5DbjncqmThLjc2sVKG+zVffgkD4K2foRXjlOsxN0+nNWDmmRwwSzkENXQ== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.2.0" + +victory@^35.1.1: + version "35.2.0" + resolved "https://registry.yarnpkg.com/victory/-/victory-35.2.0.tgz#2fdb76fd6cc56a8f1ee9a3bf848c8e24703281ad" + integrity sha512-G33seLKbpE73S5WrXatfMT+CpxFXz4MzVSWSL3gah6KeVYunnK7WBkg9Xvwt+zJx5XMaRru8yWamtui5cg6UVg== + dependencies: + victory-area "^35.2.0" + victory-axis "^35.2.0" + victory-bar "^35.2.0" + victory-box-plot "^35.2.0" + victory-brush-container "^35.2.0" + victory-brush-line "^35.2.0" + victory-candlestick "^35.2.0" + victory-chart "^35.2.0" + victory-core "^35.2.0" + victory-create-container "^35.2.0" + victory-cursor-container "^35.2.0" + victory-errorbar "^35.2.0" + victory-group "^35.2.0" + victory-histogram "^35.2.0" + victory-legend "^35.2.0" + victory-line "^35.2.0" + victory-pie "^35.2.0" + victory-polar-axis "^35.2.0" + victory-scatter "^35.2.0" + victory-selection-container "^35.2.0" + victory-shared-events "^35.2.0" + victory-stack "^35.2.0" + victory-tooltip "^35.2.0" + victory-voronoi "^35.2.0" + victory-voronoi-container "^35.2.0" + victory-zoom-container "^35.2.0" + vm-browserify@1.1.2, vm-browserify@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" From f001904e350cc3b7c0dd6d6489aaf37b8d64ee2d Mon Sep 17 00:00:00 2001 From: Ginger Wong Date: Sat, 10 Oct 2020 18:48:29 -0700 Subject: [PATCH 08/14] eslint rule updates for typescript --- web/.eslintrc.js | 24 ++++++++++++++++++++++++ web/pages/index2.tsx | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/web/.eslintrc.js b/web/.eslintrc.js index 2a2d06767..02acbf71d 100644 --- a/web/.eslintrc.js +++ b/web/.eslintrc.js @@ -23,5 +23,29 @@ module.exports = { "react/react-in-jsx-scope": "off", "react/jsx-filename-extension": [1, { extensions: [".js", ".jsx", ".tsx"] }], "react/jsx-props-no-spreading": "off", + + 'no-unused-vars': 'off', + '@typescript-eslint/no-unused-vars': 'error', + + 'no-use-before-define': [0], + '@typescript-eslint/no-use-before-define': [1], + + "import/extensions": [ + "error", + "ignorePackages", + { + "js": "never", + "jsx": "never", + "ts": "never", + "tsx": "never" + } + ] + }, + settings: { + "import/resolver": { + "node": { + "extensions": [".js", ".jsx", ".ts", ".tsx"] + } + } }, }; diff --git a/web/pages/index2.tsx b/web/pages/index2.tsx index acfd6f339..e085ba74e 100644 --- a/web/pages/index2.tsx +++ b/web/pages/index2.tsx @@ -14,7 +14,7 @@ export default function Admin() { console.log("====",{count, result}) setBroadcasterStatus({ ...result, broadcastActive }); - setCount(count => count + 1); + setCount(c => c + 1); } catch (error) { setBroadcasterStatus({ ...broadcasterStatus, message: error.message }); From 98ae9c43d336c5cfaac452b00e31543be890638d Mon Sep 17 00:00:00 2001 From: Ginger Wong Date: Sun, 11 Oct 2020 19:46:48 -0700 Subject: [PATCH 09/14] add notes; remove victory charts, try recharts --- web/package.json | 4 +- web/pages/_app.tsx | 7 +- web/pages/components/connected-clients.tsx | 13 +- web/pages/components/hardware-info.tsx | 4 +- web/pages/components/viewer-info.tsx | 23 +- web/pages/home.tsx | 8 +- web/yarn.lock | 462 ++++++--------------- 7 files changed, 160 insertions(+), 361 deletions(-) diff --git a/web/package.json b/web/package.json index a6f6052c6..8d8a35bd0 100644 --- a/web/package.json +++ b/web/package.json @@ -14,8 +14,8 @@ "prop-types": "^15.7.2", "react": "16.13.1", "react-dom": "16.13.1", - "sass": "^1.26.11", - "victory": "^35.1.1" + "recharts": "^1.8.5", + "sass": "^1.26.11" }, "devDependencies": { "@types/node": "^14.11.2", diff --git a/web/pages/_app.tsx b/web/pages/_app.tsx index d53ae791f..22af59f11 100644 --- a/web/pages/_app.tsx +++ b/web/pages/_app.tsx @@ -1,5 +1,8 @@ -import 'antd/dist/antd.css'; -import '../styles/globals.scss' +// import 'antd/dist/antd.css'; +// import '../styles/globals.scss' + +import 'antd/dist/antd.dark.css'; +import 'antd/dist/antd.compact.css'; import { AppProps } from 'next/app' diff --git a/web/pages/components/connected-clients.tsx b/web/pages/components/connected-clients.tsx index 4261949e1..82db5091d 100644 --- a/web/pages/components/connected-clients.tsx +++ b/web/pages/components/connected-clients.tsx @@ -4,10 +4,19 @@ import { CONNECTED_CLIENTS, fetchData, FETCH_INTERVAL } from '../utils/apis'; export default function HardwareInfo() { const [clients, setClients] = useState({}); +/* +geo data looks like this + "geo": { + "countryCode": "US", + "regionName": "California", + "timeZone": "America/Los_Angeles" + } +*/ + const getInfo = async () => { try { const result = await fetchData(CONNECTED_CLIENTS); - console.log("viewers result", result) + console.log("================ result", result) setClients({ ...result }); @@ -31,6 +40,8 @@ export default function HardwareInfo() { return (

Connected Clients

+

a table of info..

+

who's watching, how long they've been there, have they chatted? where they from?

{JSON.stringify(clients)}
diff --git a/web/pages/components/hardware-info.tsx b/web/pages/components/hardware-info.tsx index bfdd8ac67..919489c2e 100644 --- a/web/pages/components/hardware-info.tsx +++ b/web/pages/components/hardware-info.tsx @@ -20,7 +20,7 @@ export default function HardwareInfo() { let getStatusIntervalId = null; getHardwareStatus(); - getStatusIntervalId = setInterval(getHardwareStatus, FETCH_INTERVAL); + getStatusIntervalId = setInterval(getHardwareStatus, FETCH_INTERVAL); //runs every 1 min. // returned function will be called on component unmount return () => { @@ -31,6 +31,8 @@ export default function HardwareInfo() { return (

Hardware Info

+

cpu:[], disk: [], memory: []; value = %age.

+

the times should be the same for each, though milliseconds differ

{JSON.stringify(hardwareStatus)}
diff --git a/web/pages/components/viewer-info.tsx b/web/pages/components/viewer-info.tsx index dfb034f83..e443e3f12 100644 --- a/web/pages/components/viewer-info.tsx +++ b/web/pages/components/viewer-info.tsx @@ -1,18 +1,22 @@ import React, { useState, useEffect } from 'react'; -import { VIEWERS_OVER_TIME, fetchData, FETCH_INTERVAL } from '../utils/apis'; +import { VIEWERS_OVER_TIME, fetchData } from '../utils/apis'; -export default function HardwareInfo() { - const [viewerInfo, setViewerInfo] = useState({}); + +const FETCH_INTERVAL = 5 * 60 * 1000; // 5 mins + +export default function ViewersOverTime() { + const [viewerInfo, setViewerInfo] = useState([]); const getInfo = async () => { try { const result = await fetchData(VIEWERS_OVER_TIME); console.log("viewers result", result) - setViewerInfo({ ...result }); + setViewerInfo(result); } catch (error) { - setViewerInfo({ ...viewerInfo, message: error.message }); + console.log("==== error", error) + // setViewerInfo({ ...viewerInfo, message: error.message }); } }; @@ -28,11 +32,18 @@ export default function HardwareInfo() { } }, []); + + const formattedData = viewerInfo.map(viewer => ({ + x: (new Date(viewer.time)).toLocaleTimeString(), + y: viewer.value, + })); + return (

Viewers over time

+

Time on X axis, # Viewer on Y

- {JSON.stringify(viewerInfo)} + {JSON.stringify(formattedData)}
); diff --git a/web/pages/home.tsx b/web/pages/home.tsx index cd63d9fc4..ea76aaa52 100644 --- a/web/pages/home.tsx +++ b/web/pages/home.tsx @@ -3,6 +3,7 @@ import React, { useState, useEffect } from 'react'; import BroadcastInfo from './components/broadcast-info'; import HardwareInfo from './components/hardware-info'; import ViewerInfo from './components/viewer-info'; +import ServerConfig from './components/server-config'; import ConnectedClients from './components/connected-clients'; export default function HomeView(props) { @@ -10,10 +11,11 @@ export default function HomeView(props) { const broadcastDetails = broadcastActive ? ( <> - - + {/* + */} - + {/* + */} ) : null; diff --git a/web/yarn.lock b/web/yarn.lock index 46cf3dbff..f3a35f681 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -1020,7 +1020,7 @@ core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" -"@babel/runtime@7.11.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.8.4": +"@babel/runtime@7.11.2", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.8.4": version "7.11.2" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736" integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw== @@ -1747,6 +1747,11 @@ babel-plugin-transform-react-remove-prop-types@0.4.24: resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a" integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA== +balanced-match@^0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" + integrity sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg= + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -2287,6 +2292,11 @@ core-js-pure@^3.0.0: resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813" integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA== +core-js@^2.6.10: + version "2.6.11" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" + integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== + core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -2448,11 +2458,6 @@ d3-array@^1.2.0: resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f" integrity sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw== -d3-array@^2.4.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-2.8.0.tgz#f76e10ad47f1f4f75f33db5fc322eb9ffde5ef23" - integrity sha512-6V272gsOeg7+9pTW1jSYOR1QE37g95I3my1hBmY+vOUNHRrk9yt4OTz/gK7PMkVAVDrYYq4mq3grTiZ8iJdNIw== - d3-collection@1: version "1.0.7" resolved "https://registry.yarnpkg.com/d3-collection/-/d3-collection-1.0.7.tgz#349bd2aa9977db071091c13144d5e4f16b5b310e" @@ -2463,17 +2468,12 @@ d3-color@1: resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-1.4.1.tgz#c52002bf8846ada4424d55d97982fef26eb3bc8a" integrity sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q== -d3-ease@^1.0.0: - version "1.0.7" - resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-1.0.7.tgz#9a834890ef8b8ae8c558b2fe55bd57f5993b85e2" - integrity sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ== - d3-format@1: version "1.4.5" resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.4.5.tgz#374f2ba1320e3717eb74a9356c67daee17a7edb4" integrity sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ== -d3-interpolate@1, d3-interpolate@^1.1.1: +d3-interpolate@1, d3-interpolate@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-1.4.0.tgz#526e79e2d80daa383f9e0c1c1c7dcc0f0583e987" integrity sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA== @@ -2485,20 +2485,19 @@ d3-path@1: resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.9.tgz#48c050bb1fe8c262493a8caf5524e3e9591701cf" integrity sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg== -d3-scale@^1.0.0: - version "1.0.7" - resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-1.0.7.tgz#fa90324b3ea8a776422bd0472afab0b252a0945d" - integrity sha512-KvU92czp2/qse5tUfGms6Kjig0AhHOwkzXG0+PqIJB3ke0WUv088AHMZI0OssO9NCkXt4RP8yju9rpH8aGB7Lw== +d3-scale@^2.1.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-2.2.2.tgz#4e880e0b2745acaaddd3ede26a9e908a9e17b81f" + integrity sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw== dependencies: d3-array "^1.2.0" d3-collection "1" - d3-color "1" d3-format "1" d3-interpolate "1" d3-time "1" d3-time-format "2" -d3-shape@^1.0.0, d3-shape@^1.2.0: +d3-shape@^1.2.0: version "1.3.7" resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.3.7.tgz#df63801be07bc986bc54f63789b4fe502992b5d7" integrity sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw== @@ -2517,16 +2516,6 @@ d3-time@1: resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.1.0.tgz#b1e19d307dae9c900b7e5b25ffc5dcc249a8a0f1" integrity sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA== -d3-timer@^1.0.0: - version "1.0.10" - resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-1.0.10.tgz#dfe76b8a91748831b13b6d9c793ffbd508dd9de5" - integrity sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw== - -d3-voronoi@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/d3-voronoi/-/d3-voronoi-1.1.4.tgz#dd3c78d7653d2bb359284ae478645d95944c8297" - integrity sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg== - d@1, d@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" @@ -2571,6 +2560,11 @@ debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: dependencies: ms "2.0.0" +decimal.js-light@^2.4.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/decimal.js-light/-/decimal.js-light-2.5.1.tgz#134fd32508f19e208f4fb2f8dac0d2626a867934" + integrity sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg== + decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" @@ -2610,18 +2604,6 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" -delaunator@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-4.0.1.tgz#3d779687f57919a7a418f8ab947d3bddb6846957" - integrity sha512-WNPWi1IRKZfCt/qIDMfERkDp93+iZEmOxN2yy4Jg+Xhv8SLk2UTqqbe1sfiipn0and9QrE914/ihdx82Y/Giag== - -delaunay-find@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/delaunay-find/-/delaunay-find-0.0.5.tgz#5fb37e6509da934881b4b16c08898ac89862c097" - integrity sha512-7yAJ/wmKWj3SgqjtkGqT/RCwI0HWAo5YnHMoF5nYXD8cdci+YSo23iPmgrZUNOpDxRWN91PqxUvMMr2lKpjr+w== - dependencies: - delaunator "^4.0.0" - des.js@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" @@ -2673,6 +2655,13 @@ dom-align@^1.7.0: resolved "https://registry.yarnpkg.com/dom-align/-/dom-align-1.12.0.tgz#56fb7156df0b91099830364d2d48f88963f5a29c" integrity sha512-YkoezQuhp3SLFGdOlr5xkqZ640iXrnHAwVYcDg8ZKRUtO7mSzSC2BA5V0VuyAwPSJA4CLIc6EDDJh4bEsD2+zA== +dom-helpers@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8" + integrity sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA== + dependencies: + "@babel/runtime" "^7.1.2" + dom-serializer@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.0.1.tgz#79695eb49af3cd8abc8d93a73da382deb1ca0795" @@ -4079,12 +4068,22 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= + lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= -lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20: +lodash.throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" + integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ= + +lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.5, lodash@~4.17.4: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== @@ -4137,6 +4136,11 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +math-expression-evaluator@^1.2.14: + version "1.2.22" + resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.22.tgz#c14dcb3d8b4d150e5dcea9c68c8dad80309b0d5e" + integrity sha512-L0j0tFVZBQQLeEjmWOvDLoRciIY8gQGWahvkztXUal8jH8R5Rlqo9GCvgqvXcy9LQhEWdQCVvzqAbxgYNt4blQ== + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -4969,7 +4973,7 @@ promise-inflight@^1.0.1: resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= -prop-types@15.7.2, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@15.7.2, prop-types@^15.5.10, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -5433,11 +5437,6 @@ react-dom@16.13.1: prop-types "^15.6.2" scheduler "^0.19.1" -react-fast-compare@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9" - integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw== - react-is@16.13.1, react-is@^16.12.0, react-is@^16.7.0, react-is@^16.8.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" @@ -5453,6 +5452,36 @@ react-refresh@0.8.3: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f" integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg== +react-resize-detector@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/react-resize-detector/-/react-resize-detector-2.3.0.tgz#57bad1ae26a28a62a2ddb678ba6ffdf8fa2b599c" + integrity sha512-oCAddEWWeFWYH5FAcHdBYcZjAw9fMzRUK9sWSx6WvSSOPVRxcHd5zTIGy/mOus+AhN/u6T4TMiWxvq79PywnJQ== + dependencies: + lodash.debounce "^4.0.8" + lodash.throttle "^4.1.1" + prop-types "^15.6.0" + resize-observer-polyfill "^1.5.0" + +react-smooth@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/react-smooth/-/react-smooth-1.0.5.tgz#94ae161d7951cdd893ccb7099d031d342cb762ad" + integrity sha512-eW057HT0lFgCKh8ilr0y2JaH2YbNcuEdFpxyg7Gf/qDKk9hqGMyXryZJ8iMGJEuKH0+wxS0ccSsBBB3W8yCn8w== + dependencies: + lodash "~4.17.4" + prop-types "^15.6.0" + raf "^3.4.0" + react-transition-group "^2.5.0" + +react-transition-group@^2.5.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d" + integrity sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg== + dependencies: + dom-helpers "^3.4.0" + loose-envify "^1.4.0" + prop-types "^15.6.2" + react-lifecycles-compat "^3.0.4" + react@16.13.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e" @@ -5517,6 +5546,46 @@ readdirp@~3.4.0: dependencies: picomatch "^2.2.1" +recharts-scale@^0.4.2: + version "0.4.3" + resolved "https://registry.yarnpkg.com/recharts-scale/-/recharts-scale-0.4.3.tgz#040b4f638ed687a530357292ecac880578384b59" + integrity sha512-t8p5sccG9Blm7c1JQK/ak9O8o95WGhNXD7TXg/BW5bYbVlr6eCeRBNpgyigD4p6pSSMehC5nSvBUPj6F68rbFA== + dependencies: + decimal.js-light "^2.4.1" + +recharts@^1.8.5: + version "1.8.5" + resolved "https://registry.yarnpkg.com/recharts/-/recharts-1.8.5.tgz#ca94a3395550946334a802e35004ceb2583fdb12" + integrity sha512-tM9mprJbXVEBxjM7zHsIy6Cc41oO/pVYqyAsOHLxlJrbNBuLs0PHB3iys2M+RqCF0//k8nJtZF6X6swSkWY3tg== + dependencies: + classnames "^2.2.5" + core-js "^2.6.10" + d3-interpolate "^1.3.0" + d3-scale "^2.1.0" + d3-shape "^1.2.0" + lodash "^4.17.5" + prop-types "^15.6.0" + react-resize-detector "^2.3.0" + react-smooth "^1.0.5" + recharts-scale "^0.4.2" + reduce-css-calc "^1.3.0" + +reduce-css-calc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716" + integrity sha1-dHyRTgSWFKTJz7umKYca0dKSdxY= + dependencies: + balanced-match "^0.4.2" + math-expression-evaluator "^1.2.14" + reduce-function-call "^1.0.1" + +reduce-function-call@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/reduce-function-call/-/reduce-function-call-1.0.3.tgz#60350f7fb252c0a67eb10fd4694d16909971300f" + integrity sha512-Hl/tuV2VDgWgCSEeWMLwxLZqX7OK59eU1guxXsRKTAyeYimivsKdtcV4fu3r710tpG5GmDKDhQ0HSZLExnNmyQ== + dependencies: + balanced-match "^1.0.0" + regenerate-unicode-properties@^8.2.0: version "8.2.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" @@ -6531,305 +6600,6 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -victory-area@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-area/-/victory-area-35.2.0.tgz#6e47a97d627e66da3609e08068802026aba29e21" - integrity sha512-07QHwpZtyLmJoUJjX3HNSE9fDHV9Z2vExEze4HO9MjBA9+zx7d5OgCsYJlPafU2Y1FFgIgLmgYTBW4OO9e/yIQ== - dependencies: - d3-shape "^1.2.0" - lodash "^4.17.19" - prop-types "^15.5.8" - victory-core "^35.2.0" - -victory-axis@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-axis/-/victory-axis-35.2.0.tgz#ae747d19c38dd30f2e80296cb11b944f6e99707c" - integrity sha512-6OlAMGtbBwkRcx8YyPqMjjS7JfoYWWZ2OPM2Zxm04dCy94LO2eZqC31IV7SHW3A0h/+j33JDnkLrbuaAWOf+hw== - dependencies: - lodash "^4.17.19" - prop-types "^15.5.8" - victory-core "^35.2.0" - -victory-bar@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-bar/-/victory-bar-35.2.0.tgz#2cfde9d7f390cce24ddf82106d1220e0c81a9cce" - integrity sha512-QyLPhrL/8pFFGX04aq5hUsaIFcB9OOD5b+9PujpobHZjLICHlkkY25SBV1bKTBkzblxZF+kldNHS60EovCNNhw== - dependencies: - d3-shape "^1.2.0" - lodash "^4.17.19" - prop-types "^15.5.8" - victory-core "^35.2.0" - -victory-box-plot@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-box-plot/-/victory-box-plot-35.2.0.tgz#8691b5fb5449006532c6b887769c0f5678f0f60c" - integrity sha512-6HWVo/7QTnYiN6MExis9mmiCb45HRAfidW31CBQ8jCf6k//DOPYpKBPNJfChosdr2f5DUS42bQXlvraCdmDSRA== - dependencies: - d3-array "^1.2.0" - lodash "^4.17.19" - prop-types "^15.5.8" - victory-core "^35.2.0" - -victory-brush-container@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-brush-container/-/victory-brush-container-35.2.0.tgz#cec3994a332490e1d6e9c756e5a1d71a93234d9c" - integrity sha512-KgfdxiP5/ka18uu+gvgDizTMa+RknKforIX6sE9Kx++BvX3QZZvS7N6wmiot7jud4Pyo90rtxJoRG4NigIxVWA== - dependencies: - lodash "^4.17.19" - prop-types "^15.5.8" - react-fast-compare "^2.0.0" - victory-core "^35.2.0" - -victory-brush-line@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-brush-line/-/victory-brush-line-35.2.0.tgz#2657057eb8a48ed2ad847f86f2a24a4fe9fceeab" - integrity sha512-9NAszFUobuOE3cLIdXHQJJ5V41INo5iMJQg5lbhJRI83QQsw4gNIYpRPr3CBhjTaPBDvfVxwEubUBfwWAE/jWg== - dependencies: - lodash "^4.17.19" - prop-types "^15.5.8" - react-fast-compare "^2.0.0" - victory-core "^35.2.0" - -victory-candlestick@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-candlestick/-/victory-candlestick-35.2.0.tgz#ca6cafd24b4ee9784cbef56a14eedfda225f9581" - integrity sha512-lYia+78umewrD5Rcl+YpBHweoyAf/OAWaCP164BWOCDrp8WQ7a4h6xD6FCk0btAvi8sC8WUsPeA5tIe+YtnFCQ== - dependencies: - lodash "^4.17.19" - prop-types "^15.5.8" - victory-core "^35.2.0" - -victory-chart@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-chart/-/victory-chart-35.2.0.tgz#42deb6988c79ff2d3a1bd3c2c869666bb58c399b" - integrity sha512-Jn/hlSEJh6pOlSyBvVzoQti5gWilKmWR9qew2HsO7NyZSwkxUI41I9kh+0YlzbScT4ANIq2bJxgaQrH9qeGBFg== - dependencies: - lodash "^4.17.19" - prop-types "^15.5.8" - react-fast-compare "^2.0.0" - victory-axis "^35.2.0" - victory-core "^35.2.0" - victory-polar-axis "^35.2.0" - victory-shared-events "^35.2.0" - -victory-core@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-core/-/victory-core-35.2.0.tgz#65b00995648fd149f0ef3e2121f441dfd775dc9e" - integrity sha512-ha4j1vfWKEJVhN1NT61Aoq1WJbpLWG4RSHuuDaTyRkdp2Zz2mYEo+F0UAYxbcXhcdE3fik4ZZULiv8ve64fIYw== - dependencies: - d3-ease "^1.0.0" - d3-interpolate "^1.1.1" - d3-scale "^1.0.0" - d3-shape "^1.2.0" - d3-timer "^1.0.0" - lodash "^4.17.19" - prop-types "^15.5.8" - react-fast-compare "^2.0.0" - -victory-create-container@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-create-container/-/victory-create-container-35.2.0.tgz#dd2cec040fa7189ec59cff9114df6b97c3332609" - integrity sha512-krxZpJKSwMDc6sfAeSRkjF6tdDa7P12LFOCA9unW33Vr2WsQQs8s6+ol+fch8TFB8i5Q6yDISRj69sxzQztwzA== - dependencies: - lodash "^4.17.19" - victory-brush-container "^35.2.0" - victory-core "^35.2.0" - victory-cursor-container "^35.2.0" - victory-selection-container "^35.2.0" - victory-voronoi-container "^35.2.0" - victory-zoom-container "^35.2.0" - -victory-cursor-container@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-cursor-container/-/victory-cursor-container-35.2.0.tgz#b5f04357c991253cfe894ffa89e2be200b8a17f2" - integrity sha512-VIl1h15Js2Mvkd1YOAgiFKuOxV+Lsn+GcbWS3gPuDDZlTVL82+n/nmcBXf+t6v41tZz9GUfcVphp8MCAT/tiog== - dependencies: - lodash "^4.17.19" - prop-types "^15.5.8" - victory-core "^35.2.0" - -victory-errorbar@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-errorbar/-/victory-errorbar-35.2.0.tgz#bd5897628d042fdada078d8379e009803dad41ff" - integrity sha512-JamxvyjxHwcbJU7eV3HnGbi1SdhvoOKC3zadJr/e/jItMtJrMQWIdErpj/XcL9ScQkLBEq8Plzya3YQo7tSvKA== - dependencies: - lodash "^4.17.19" - prop-types "^15.5.8" - victory-core "^35.2.0" - -victory-group@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-group/-/victory-group-35.2.0.tgz#f314b50f2a617c7248708ad3cd0bd10a3f7d083a" - integrity sha512-crv7to0RkJktrRk8fNoPuXsEYCplQk9Q+BV0AxLTEnPkRyxgUCjHgEgqQ8wqCXfPLYtyjUUteJhGDjinm3e4FQ== - dependencies: - lodash "^4.17.19" - prop-types "^15.5.8" - react-fast-compare "^2.0.0" - victory-core "^35.2.0" - victory-shared-events "^35.2.0" - -victory-histogram@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-histogram/-/victory-histogram-35.2.0.tgz#be97f87b3fa7ddeafe6ef1e6602f1703b28fa63e" - integrity sha512-Rl7BO8FVtOW7dbgtcDc1iNbZWRKBpACtauIgOAPeFwRfohTPOGzbFTiayo/5eqm7wHR4NfB94MY63eOD2vozqQ== - dependencies: - d3-array "^2.4.0" - d3-scale "^1.0.0" - lodash "^4.17.19" - prop-types "^15.5.8" - react-fast-compare "^2.0.0" - victory-bar "^35.2.0" - victory-core "^35.2.0" - -victory-legend@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-legend/-/victory-legend-35.2.0.tgz#741fed1db9d1e93c29094c23dd6d2b0381f63915" - integrity sha512-PiAD3pMg8E7scRRfSHRxgXjWS1xFY0t3BXLYEN4NzxDIyYshHZTWAfn5kOnEDuugd7vovEsog+kyMyXhy/miIg== - dependencies: - lodash "^4.17.19" - prop-types "^15.5.8" - victory-core "^35.2.0" - -victory-line@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-line/-/victory-line-35.2.0.tgz#99edb0d78db4335fb2d7ffb9bd1a6007edad3e22" - integrity sha512-Rx51MW46yJfOvGpj71FfYAPOBdSUPQYTpSFdKUEmtFoZwu84dUtHiAbmISk8d8vQTYJDDsGFxgmi2XantR13RA== - dependencies: - d3-shape "^1.2.0" - lodash "^4.17.19" - prop-types "^15.5.8" - victory-core "^35.2.0" - -victory-pie@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-pie/-/victory-pie-35.2.0.tgz#728ea5b8b35fc7a87c69681c8863a370b3c495c4" - integrity sha512-nt9iRb2GGcKE46bmG8P5LbX+ouYQJi4/e85rfGjUtEVusz2jo2mQ17eeQpZJAJi9R7WlUtM33MxnaqtnZwHYjA== - dependencies: - d3-shape "^1.0.0" - lodash "^4.17.19" - prop-types "^15.5.8" - victory-core "^35.2.0" - -victory-polar-axis@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-polar-axis/-/victory-polar-axis-35.2.0.tgz#cdd3237bfdcd2ca82d7beff1d2eb75c3c25a302d" - integrity sha512-kZJz1ecEN90ycvEWt3scYlsZUAVddpy/nE0MVok/ALI6LU9cJ1cGBvwTxhtXSjs8Yfcl7G3l880MhWIqG5JdyQ== - dependencies: - lodash "^4.17.19" - prop-types "^15.5.8" - victory-core "^35.2.0" - -victory-scatter@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-scatter/-/victory-scatter-35.2.0.tgz#bb691587c278e2890b43063290292bb0858c18c2" - integrity sha512-C/yjqT5z2ymWu0vPUZFbiEchLSbwCoo/Fwv6VHfia/sI05W1huZ9+5voUstMe9SqLnT/31XF+lUb+xIffcE6qg== - dependencies: - lodash "^4.17.19" - prop-types "^15.5.8" - victory-core "^35.2.0" - -victory-selection-container@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-selection-container/-/victory-selection-container-35.2.0.tgz#2ad22f05bce7e740c333b65e75f3255b3e2fd61e" - integrity sha512-mHvTdGxClA2m0HBIleg578GGcsRp7qLL8Rj2n8/iFetzLf9GLE9CtF+a1HKd8yLAeij6XmCNq8MIvO4ERg725g== - dependencies: - lodash "^4.17.19" - prop-types "^15.5.8" - victory-core "^35.2.0" - -victory-shared-events@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-shared-events/-/victory-shared-events-35.2.0.tgz#345e11acf3cd91a1ea98a406072519161486e97c" - integrity sha512-M+dvtCwK/YsnZ6ruKjrir0WfK0n5b63tLer3GwdiEdMyaWgn4hEDhafpH5PYagyG00ujSqadgf3DMRQoimv+dw== - dependencies: - lodash "^4.17.19" - prop-types "^15.5.8" - react-fast-compare "^2.0.0" - victory-core "^35.2.0" - -victory-stack@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-stack/-/victory-stack-35.2.0.tgz#b2005101b85edfb62af1692f6d9173bd80f41b5c" - integrity sha512-ofNCYpTj5Qq8ruYLFo46aQ4WyNZ514wqZUytGhs9+muJTClCjmnP4f6jfbsghZbPPucv0fGwABoiXcYIc+fJ5Q== - dependencies: - lodash "^4.17.19" - prop-types "^15.5.8" - react-fast-compare "^2.0.0" - victory-core "^35.2.0" - victory-shared-events "^35.2.0" - -victory-tooltip@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-tooltip/-/victory-tooltip-35.2.0.tgz#56189f6d61ba4262405e32a84a2ee75d98826db2" - integrity sha512-w6M2g+c0ZFfKM80Cife/9kCOd3xiXSaSCjdokp2GRBA8zD9CkbiCAGYLsF+CQBSoeZpMCyzC6bsiEtzb4SD48g== - dependencies: - lodash "^4.17.19" - prop-types "^15.5.8" - victory-core "^35.2.0" - -victory-voronoi-container@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-voronoi-container/-/victory-voronoi-container-35.2.0.tgz#38155b9c97836eb1785ac2720e9c3204b37d33ac" - integrity sha512-mevciZwcVuQ9k4PqTSz/3hSF+XyHR1DbYoZsAZJlocsezncYtdxKYbw7MOraubio/H5wCgsICi/llmxiPFmPHg== - dependencies: - delaunay-find "0.0.5" - lodash "^4.17.19" - prop-types "^15.5.8" - react-fast-compare "^2.0.0" - victory-core "^35.2.0" - victory-tooltip "^35.2.0" - -victory-voronoi@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-voronoi/-/victory-voronoi-35.2.0.tgz#e6d7341566dff915ac597baa660961f8f52b469e" - integrity sha512-TJ6t2Bxl5wu451igdJ/vIKddBIHxSJgGbuGybYgj0CTjl4KH9U16Gx8ILILm2bW07/Am1PFWQpjFjK+3Gn5NdA== - dependencies: - d3-voronoi "^1.1.2" - lodash "^4.17.19" - prop-types "^15.5.8" - victory-core "^35.2.0" - -victory-zoom-container@^35.2.0: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory-zoom-container/-/victory-zoom-container-35.2.0.tgz#94e869ce6e6eca22816e1575402c7e304af39a6f" - integrity sha512-cmR5IAfL92+ESYk6klwxINlFAQ5kO5DbjncqmThLjc2sVKG+zVffgkD4K2foRXjlOsxN0+nNWDmmRwwSzkENXQ== - dependencies: - lodash "^4.17.19" - prop-types "^15.5.8" - victory-core "^35.2.0" - -victory@^35.1.1: - version "35.2.0" - resolved "https://registry.yarnpkg.com/victory/-/victory-35.2.0.tgz#2fdb76fd6cc56a8f1ee9a3bf848c8e24703281ad" - integrity sha512-G33seLKbpE73S5WrXatfMT+CpxFXz4MzVSWSL3gah6KeVYunnK7WBkg9Xvwt+zJx5XMaRru8yWamtui5cg6UVg== - dependencies: - victory-area "^35.2.0" - victory-axis "^35.2.0" - victory-bar "^35.2.0" - victory-box-plot "^35.2.0" - victory-brush-container "^35.2.0" - victory-brush-line "^35.2.0" - victory-candlestick "^35.2.0" - victory-chart "^35.2.0" - victory-core "^35.2.0" - victory-create-container "^35.2.0" - victory-cursor-container "^35.2.0" - victory-errorbar "^35.2.0" - victory-group "^35.2.0" - victory-histogram "^35.2.0" - victory-legend "^35.2.0" - victory-line "^35.2.0" - victory-pie "^35.2.0" - victory-polar-axis "^35.2.0" - victory-scatter "^35.2.0" - victory-selection-container "^35.2.0" - victory-shared-events "^35.2.0" - victory-stack "^35.2.0" - victory-tooltip "^35.2.0" - victory-voronoi "^35.2.0" - victory-voronoi-container "^35.2.0" - victory-zoom-container "^35.2.0" - vm-browserify@1.1.2, vm-browserify@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" From 654f70dcf9dcd2b596e061014653f719e9bc3336 Mon Sep 17 00:00:00 2001 From: Ginger Wong Date: Sun, 11 Oct 2020 21:46:07 -0700 Subject: [PATCH 10/14] initial line chart setup with d3 help --- web/package-lock.json | 592 +++++++++------------------ web/package.json | 2 + web/pages/components/viewer-info.tsx | 23 +- web/pages/utils/apis.ts | 5 - web/yarn.lock | 45 ++ 5 files changed, 257 insertions(+), 410 deletions(-) diff --git a/web/package-lock.json b/web/package-lock.json index 1bfd1e339..fc2592dd9 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -2685,6 +2685,11 @@ "toggle-selection": "^1.0.6" } }, + "core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" + }, "core-js-compat": { "version": "3.6.5", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz", @@ -2905,9 +2910,9 @@ } }, "d3-array": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", - "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==" + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.8.0.tgz", + "integrity": "sha512-6V272gsOeg7+9pTW1jSYOR1QE37g95I3my1hBmY+vOUNHRrk9yt4OTz/gK7PMkVAVDrYYq4mq3grTiZ8iJdNIw==" }, "d3-collection": { "version": "1.0.7", @@ -2915,26 +2920,21 @@ "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==" }, "d3-color": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz", - "integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==" - }, - "d3-ease": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz", - "integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-2.0.0.tgz", + "integrity": "sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ==" }, "d3-format": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz", - "integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-2.0.0.tgz", + "integrity": "sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA==" }, "d3-interpolate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz", - "integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-2.0.1.tgz", + "integrity": "sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ==", "requires": { - "d3-color": "1" + "d3-color": "1 - 2" } }, "d3-path": { @@ -2943,17 +2943,15 @@ "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==" }, "d3-scale": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-1.0.7.tgz", - "integrity": "sha512-KvU92czp2/qse5tUfGms6Kjig0AhHOwkzXG0+PqIJB3ke0WUv088AHMZI0OssO9NCkXt4RP8yju9rpH8aGB7Lw==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-3.2.3.tgz", + "integrity": "sha512-8E37oWEmEzj57bHcnjPVOBS3n4jqakOeuv1EDdQSiSrYnMCBdMd3nc4HtKk7uia8DUHcY/CGuJ42xxgtEYrX0g==", "requires": { - "d3-array": "^1.2.0", - "d3-collection": "1", - "d3-color": "1", - "d3-format": "1", - "d3-interpolate": "1", - "d3-time": "1", - "d3-time-format": "2" + "d3-array": "^2.3.0", + "d3-format": "1 - 2", + "d3-interpolate": "1.2.0 - 2", + "d3-time": "1 - 2", + "d3-time-format": "2 - 3" } }, "d3-shape": { @@ -2965,28 +2963,18 @@ } }, "d3-time": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz", - "integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-2.0.0.tgz", + "integrity": "sha512-2mvhstTFcMvwStWd9Tj3e6CEqtOivtD8AUiHT8ido/xmzrI9ijrUUihZ6nHuf/vsScRBonagOdj0Vv+SEL5G3Q==" }, "d3-time-format": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz", - "integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-3.0.0.tgz", + "integrity": "sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==", "requires": { - "d3-time": "1" + "d3-time": "1 - 2" } }, - "d3-timer": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz", - "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==" - }, - "d3-voronoi": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz", - "integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==" - }, "damerau-levenshtein": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz", @@ -3019,6 +3007,11 @@ "ms": "2.1.2" } }, + "decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" + }, "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", @@ -3075,19 +3068,6 @@ } } }, - "delaunator": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-4.0.1.tgz", - "integrity": "sha512-WNPWi1IRKZfCt/qIDMfERkDp93+iZEmOxN2yy4Jg+Xhv8SLk2UTqqbe1sfiipn0and9QrE914/ihdx82Y/Giag==" - }, - "delaunay-find": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/delaunay-find/-/delaunay-find-0.0.5.tgz", - "integrity": "sha512-7yAJ/wmKWj3SgqjtkGqT/RCwI0HWAo5YnHMoF5nYXD8cdci+YSo23iPmgrZUNOpDxRWN91PqxUvMMr2lKpjr+w==", - "requires": { - "delaunator": "^4.0.0" - } - }, "des.js": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", @@ -3137,6 +3117,14 @@ "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.0.tgz", "integrity": "sha512-YkoezQuhp3SLFGdOlr5xkqZ640iXrnHAwVYcDg8ZKRUtO7mSzSC2BA5V0VuyAwPSJA4CLIc6EDDJh4bEsD2+zA==" }, + "dom-helpers": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz", + "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==", + "requires": { + "@babel/runtime": "^7.1.2" + } + }, "dom-serializer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.0.1.tgz", @@ -4968,11 +4956,21 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" + }, "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" }, + "lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=" + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -5017,6 +5015,11 @@ "object-visit": "^1.0.0" } }, + "math-expression-evaluator": { + "version": "1.2.22", + "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.22.tgz", + "integrity": "sha512-L0j0tFVZBQQLeEjmWOvDLoRciIY8gQGWahvkztXUal8jH8R5Rlqo9GCvgqvXcy9LQhEWdQCVvzqAbxgYNt4blQ==" + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -6450,11 +6453,6 @@ "scheduler": "^0.19.1" } }, - "react-fast-compare": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", - "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==" - }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -6470,6 +6468,39 @@ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz", "integrity": "sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==" }, + "react-resize-detector": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/react-resize-detector/-/react-resize-detector-2.3.0.tgz", + "integrity": "sha512-oCAddEWWeFWYH5FAcHdBYcZjAw9fMzRUK9sWSx6WvSSOPVRxcHd5zTIGy/mOus+AhN/u6T4TMiWxvq79PywnJQ==", + "requires": { + "lodash.debounce": "^4.0.8", + "lodash.throttle": "^4.1.1", + "prop-types": "^15.6.0", + "resize-observer-polyfill": "^1.5.0" + } + }, + "react-smooth": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-1.0.5.tgz", + "integrity": "sha512-eW057HT0lFgCKh8ilr0y2JaH2YbNcuEdFpxyg7Gf/qDKk9hqGMyXryZJ8iMGJEuKH0+wxS0ccSsBBB3W8yCn8w==", + "requires": { + "lodash": "~4.17.4", + "prop-types": "^15.6.0", + "raf": "^3.4.0", + "react-transition-group": "^2.5.0" + } + }, + "react-transition-group": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz", + "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==", + "requires": { + "dom-helpers": "^3.4.0", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2", + "react-lifecycles-compat": "^3.0.4" + } + }, "read-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", @@ -6583,6 +6614,108 @@ "readable-stream": "^2.0.2" } }, + "recharts": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-1.8.5.tgz", + "integrity": "sha512-tM9mprJbXVEBxjM7zHsIy6Cc41oO/pVYqyAsOHLxlJrbNBuLs0PHB3iys2M+RqCF0//k8nJtZF6X6swSkWY3tg==", + "requires": { + "classnames": "^2.2.5", + "core-js": "^2.6.10", + "d3-interpolate": "^1.3.0", + "d3-scale": "^2.1.0", + "d3-shape": "^1.2.0", + "lodash": "^4.17.5", + "prop-types": "^15.6.0", + "react-resize-detector": "^2.3.0", + "react-smooth": "^1.0.5", + "recharts-scale": "^0.4.2", + "reduce-css-calc": "^1.3.0" + }, + "dependencies": { + "d3-array": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", + "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==" + }, + "d3-color": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz", + "integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==" + }, + "d3-format": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz", + "integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==" + }, + "d3-interpolate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz", + "integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==", + "requires": { + "d3-color": "1" + } + }, + "d3-scale": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz", + "integrity": "sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==", + "requires": { + "d3-array": "^1.2.0", + "d3-collection": "1", + "d3-format": "1", + "d3-interpolate": "1", + "d3-time": "1", + "d3-time-format": "2" + } + }, + "d3-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz", + "integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==" + }, + "d3-time-format": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz", + "integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==", + "requires": { + "d3-time": "1" + } + } + } + }, + "recharts-scale": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.3.tgz", + "integrity": "sha512-t8p5sccG9Blm7c1JQK/ak9O8o95WGhNXD7TXg/BW5bYbVlr6eCeRBNpgyigD4p6pSSMehC5nSvBUPj6F68rbFA==", + "requires": { + "decimal.js-light": "^2.4.1" + } + }, + "reduce-css-calc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", + "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", + "requires": { + "balanced-match": "^0.4.2", + "math-expression-evaluator": "^1.2.14", + "reduce-function-call": "^1.0.1" + }, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" + } + } + }, + "reduce-function-call": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.3.tgz", + "integrity": "sha512-Hl/tuV2VDgWgCSEeWMLwxLZqX7OK59eU1guxXsRKTAyeYimivsKdtcV4fu3r710tpG5GmDKDhQ0HSZLExnNmyQ==", + "requires": { + "balanced-match": "^1.0.0" + } + }, "regenerate": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", @@ -8066,339 +8199,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "victory": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory/-/victory-35.1.1.tgz", - "integrity": "sha512-PJYPP71dW73qPiemlYBtRjWuw0wmyk8rfbmeUyrzrUG/xwfeO52N96P7MXcV+dBXR4BzLy0G5D0bvGksBFfVWw==", - "requires": { - "victory-area": "^35.1.1", - "victory-axis": "^35.1.1", - "victory-bar": "^35.1.1", - "victory-box-plot": "^35.1.1", - "victory-brush-container": "^35.1.1", - "victory-brush-line": "^35.1.1", - "victory-candlestick": "^35.1.1", - "victory-chart": "^35.1.1", - "victory-core": "^35.1.1", - "victory-create-container": "^35.1.1", - "victory-cursor-container": "^35.1.1", - "victory-errorbar": "^35.1.1", - "victory-group": "^35.1.1", - "victory-histogram": "^35.1.1", - "victory-legend": "^35.1.1", - "victory-line": "^35.1.1", - "victory-pie": "^35.1.1", - "victory-polar-axis": "^35.1.1", - "victory-scatter": "^35.1.1", - "victory-selection-container": "^35.1.1", - "victory-shared-events": "^35.1.1", - "victory-stack": "^35.1.1", - "victory-tooltip": "^35.1.1", - "victory-voronoi": "^35.1.1", - "victory-voronoi-container": "^35.1.1", - "victory-zoom-container": "^35.1.1" - } - }, - "victory-area": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-area/-/victory-area-35.1.1.tgz", - "integrity": "sha512-Ghh4x7GEhR8LQo1duy4mKzCMVpxOzlYf2H8Wwvh3TwOMitwbfBZ91P9bYOv3KEsVxfzmbuGM4fKfkJEFcwXQiA==", - "requires": { - "d3-shape": "^1.2.0", - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "victory-core": "^35.1.1" - } - }, - "victory-axis": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-axis/-/victory-axis-35.1.1.tgz", - "integrity": "sha512-HQkGTHKgk32vjPrGG/1LNvodnywnI7fMoNHwCvJVXy+C+2N3UKB828zvdkuDtq9Cc4GSPBWsMzPJxyi5kRjV6g==", - "requires": { - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "victory-core": "^35.1.1" - } - }, - "victory-bar": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-bar/-/victory-bar-35.1.1.tgz", - "integrity": "sha512-VuY286MhccpqroedPOvjy7zJbZxtHsJ/VloywrOWjjcWIGRuh+Ln3zlT/8aJC1Vs4X9+WHwAdUKVR1FTufKjkQ==", - "requires": { - "d3-shape": "^1.2.0", - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "victory-core": "^35.1.1" - } - }, - "victory-box-plot": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-box-plot/-/victory-box-plot-35.1.1.tgz", - "integrity": "sha512-B9H9G5GmQvHM6Ydy+9vTaNNh+7DtNnUe5I7DNtJt9Ou8RWckI2F3sX1pudMLRy1LHV3d1fnxxBuOADxCTo6BcA==", - "requires": { - "d3-array": "^1.2.0", - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "victory-core": "^35.1.1" - } - }, - "victory-brush-container": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-brush-container/-/victory-brush-container-35.1.1.tgz", - "integrity": "sha512-1e1Q2CJn2LMGmAwdtvDbKI6XicqLw8YSNLRcjeCBmxtMotY8yHK91G/7Wr5OwiwCkjzFDf3P4XRprHTK1t6hNg==", - "requires": { - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "react-fast-compare": "^2.0.0", - "victory-core": "^35.1.1" - } - }, - "victory-brush-line": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-brush-line/-/victory-brush-line-35.1.1.tgz", - "integrity": "sha512-kNCPUxzXij0fPkhfMkJDDHQ8N820suY5mC2Eh2g+lcwOdA3ha3w9UNxMwDNlbXOLqJs5Bw1QweWnRfIBbWNfZA==", - "requires": { - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "react-fast-compare": "^2.0.0", - "victory-core": "^35.1.1" - } - }, - "victory-candlestick": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-candlestick/-/victory-candlestick-35.1.1.tgz", - "integrity": "sha512-4h/4+d9kHCPinK45HWgpO6+k0bYzHBWDoW0rZILCGQYCNSjy4UDHF0UiP6X1QLADrV7d47ZnK83lruVcQjgxKw==", - "requires": { - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "victory-core": "^35.1.1" - } - }, - "victory-chart": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-chart/-/victory-chart-35.1.1.tgz", - "integrity": "sha512-B8dixl5RmIxmh0CPVBv/0cSjZ31FNvQmFX9t352Df4VQ5fU23hvmqCUASE2QboIcIeAiH+Qj0NKycu+lr0GgjA==", - "requires": { - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "react-fast-compare": "^2.0.0", - "victory-axis": "^35.1.1", - "victory-core": "^35.1.1", - "victory-polar-axis": "^35.1.1", - "victory-shared-events": "^35.1.1" - } - }, - "victory-core": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-core/-/victory-core-35.1.1.tgz", - "integrity": "sha512-DnWwTLPOpVLgnz52h4SY1CBUxkdxfX14cDPC4Ly8rWY7I3OXuEhzE3Wx/SYQO9vk7oQ7zp8ukWRVWpVpcEZzug==", - "requires": { - "d3-ease": "^1.0.0", - "d3-interpolate": "^1.1.1", - "d3-scale": "^1.0.0", - "d3-shape": "^1.2.0", - "d3-timer": "^1.0.0", - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "react-fast-compare": "^2.0.0" - } - }, - "victory-create-container": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-create-container/-/victory-create-container-35.1.1.tgz", - "integrity": "sha512-QDnCXKL0JovglmT7Fs7rC+GiPgXcJWlXC8LDWpo0kWXD0OP7jNwkCmO78/QU4tlcAWtVY/CNU+rBMxwDTS6/WQ==", - "requires": { - "lodash": "^4.17.19", - "victory-brush-container": "^35.1.1", - "victory-core": "^35.1.1", - "victory-cursor-container": "^35.1.1", - "victory-selection-container": "^35.1.1", - "victory-voronoi-container": "^35.1.1", - "victory-zoom-container": "^35.1.1" - } - }, - "victory-cursor-container": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-cursor-container/-/victory-cursor-container-35.1.1.tgz", - "integrity": "sha512-wD4N7k+YbHDUJleTgYqvYheN1c/qYlcZ44pXw8BKKqywtZixU8Pm9Tioo6L5e0+nSiGyJDixdvMpt2C5hGHNDw==", - "requires": { - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "victory-core": "^35.1.1" - } - }, - "victory-errorbar": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-errorbar/-/victory-errorbar-35.1.1.tgz", - "integrity": "sha512-Oz8Fwsg0kDJETnH2B8asbTmOy3uvCgIsF80rY4NKqoGYcfaqY8xhmbxz+ipMyL826+mg3WmTnqVpbdXm3Y3oXw==", - "requires": { - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "victory-core": "^35.1.1" - } - }, - "victory-group": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-group/-/victory-group-35.1.1.tgz", - "integrity": "sha512-OpSAXZ7InMXWT9AEo5UA/QYaD8i9F7pdHqvcSDckoEJPwZ6Sr7deE9LpfVo3KeK6PjzjQBZdrBPggSZwcvl0Zw==", - "requires": { - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "react-fast-compare": "^2.0.0", - "victory-core": "^35.1.1", - "victory-shared-events": "^35.1.1" - } - }, - "victory-histogram": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-histogram/-/victory-histogram-35.1.1.tgz", - "integrity": "sha512-S/CGu7nIlN8kSQMNSMRWw9Nr4x/Z9W5giix4nxfj8M1tu0epNsRED4Jav2NUn7S3z+f2N76uJo80zVk894JK+A==", - "requires": { - "d3-array": "^2.4.0", - "d3-scale": "^1.0.0", - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "react-fast-compare": "^2.0.0", - "victory-bar": "^35.1.1", - "victory-core": "^35.1.1" - }, - "dependencies": { - "d3-array": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.8.0.tgz", - "integrity": "sha512-6V272gsOeg7+9pTW1jSYOR1QE37g95I3my1hBmY+vOUNHRrk9yt4OTz/gK7PMkVAVDrYYq4mq3grTiZ8iJdNIw==" - } - } - }, - "victory-legend": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-legend/-/victory-legend-35.1.1.tgz", - "integrity": "sha512-RibASpnHin6TAXRhgngEk71Y++Wh+ikRH8nV2hygT+WtTolRj6RsAA43jQwTv4cDqt3v2k+Ddoh4eXpJoH3R2Q==", - "requires": { - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "victory-core": "^35.1.1" - } - }, - "victory-line": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-line/-/victory-line-35.1.1.tgz", - "integrity": "sha512-PAY6Q8SN0p4vBiMvBUXVNb3FrZ7BWaN3/8/pWUKKobTVSiKaJmaDXR9u9EDn7yErjwxsFqJQ8+918pfkWvWWNg==", - "requires": { - "d3-shape": "^1.2.0", - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "victory-core": "^35.1.1" - } - }, - "victory-pie": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-pie/-/victory-pie-35.1.1.tgz", - "integrity": "sha512-PFzceL0LPIK30Flz3OrEB7vSCHm5oaQInvvufuUsTUPHxBjq0QDqukV5zHCz0OfdFZ+KzqCTdwD95EFyC1yrYA==", - "requires": { - "d3-shape": "^1.0.0", - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "victory-core": "^35.1.1" - } - }, - "victory-polar-axis": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-polar-axis/-/victory-polar-axis-35.1.1.tgz", - "integrity": "sha512-Y6iFqfkkI3Be4ltg+3AsmXUkk9uDQ+IU6XQWzZ0PZGGEt1ftiRX5GS2tfTQcV//qsannX6t2xKBc0iquPI3+Kw==", - "requires": { - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "victory-core": "^35.1.1" - } - }, - "victory-scatter": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-scatter/-/victory-scatter-35.1.1.tgz", - "integrity": "sha512-IgJNQHXx7lUoFnUoMNeCatBso+sIdx6/v0Hx94GeP3X6UmGPzBnM9JlyjVQjyJuiEoWQ0MtFhqidy+CSvn4pJg==", - "requires": { - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "victory-core": "^35.1.1" - } - }, - "victory-selection-container": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-selection-container/-/victory-selection-container-35.1.1.tgz", - "integrity": "sha512-lait103pBL1h9Jv65OiR8xfXhoQ79KpjWsgx0fZQGi+HcvzaKTAv9XGAMqB6GT3PkXFEqrz9K+0cAaRHd8SPvQ==", - "requires": { - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "victory-core": "^35.1.1" - } - }, - "victory-shared-events": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-shared-events/-/victory-shared-events-35.1.1.tgz", - "integrity": "sha512-h4qMyZuvTlZAq/UuP3R6ETCLYSmggzU01ZuAbxEqygt+XQ04yG2QJmf8stKxvS1ktYFIXVdrJr/bJjTAIZQ0XQ==", - "requires": { - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "react-fast-compare": "^2.0.0", - "victory-core": "^35.1.1" - } - }, - "victory-stack": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-stack/-/victory-stack-35.1.1.tgz", - "integrity": "sha512-SKXd6YG97CH9KsQB+akhc2jos+6vjGmyJkaHuTXuqGL9TrGtTM1WA784LAOFbNourk/VRTf1TJOz0EtzO2orIw==", - "requires": { - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "react-fast-compare": "^2.0.0", - "victory-core": "^35.1.1", - "victory-shared-events": "^35.1.1" - } - }, - "victory-tooltip": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-tooltip/-/victory-tooltip-35.1.1.tgz", - "integrity": "sha512-2ZMecFgL6lQ2exzNGBmnUia967plHRWAinUYaRMSY4R3+FgOjCLkdVu1XBf/y6EBn+urIw3VK4yS8pn9ESjSOQ==", - "requires": { - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "victory-core": "^35.1.1" - } - }, - "victory-voronoi": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-voronoi/-/victory-voronoi-35.1.1.tgz", - "integrity": "sha512-b8Ec7a/253tgpC+KH2CdvAl+DubSAXWYyd30Bd6T1+oPx+KmRdB76uEmnqUHXzBCEHnkjazfOPb2nLItCoOR9g==", - "requires": { - "d3-voronoi": "^1.1.2", - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "victory-core": "^35.1.1" - } - }, - "victory-voronoi-container": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-voronoi-container/-/victory-voronoi-container-35.1.1.tgz", - "integrity": "sha512-AcCOhGMt9WYGDQtGIfbHhabdTmj92Uwr0fyfg+StrZk6AB/KgJproRcKQ91jLQExQkaoqdB9DP83LYGjWnk0zg==", - "requires": { - "delaunay-find": "0.0.5", - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "react-fast-compare": "^2.0.0", - "victory-core": "^35.1.1", - "victory-tooltip": "^35.1.1" - } - }, - "victory-zoom-container": { - "version": "35.1.1", - "resolved": "https://registry.npmjs.org/victory-zoom-container/-/victory-zoom-container-35.1.1.tgz", - "integrity": "sha512-U0sKD56muX1ZK/mBWYjdRUDtrsIRBGHC9MIpNL0Ju6sIoqH//uyBFoO617xf5VMO8iUYywjXEqzXb+60XK41TQ==", - "requires": { - "lodash": "^4.17.19", - "prop-types": "^15.5.8", - "victory-core": "^35.1.1" - } - }, "vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", diff --git a/web/package.json b/web/package.json index 8d8a35bd0..bf39b247f 100644 --- a/web/package.json +++ b/web/package.json @@ -10,6 +10,8 @@ "dependencies": { "@ant-design/icons": "^4.2.2", "antd": "^4.6.6", + "d3-scale": "^3.2.3", + "d3-time-format": "^3.0.0", "next": "9.5.3", "prop-types": "^15.7.2", "react": "16.13.1", diff --git a/web/pages/components/viewer-info.tsx b/web/pages/components/viewer-info.tsx index e443e3f12..9ee630f7c 100644 --- a/web/pages/components/viewer-info.tsx +++ b/web/pages/components/viewer-info.tsx @@ -1,4 +1,6 @@ import React, { useState, useEffect } from 'react'; +import {timeFormat} from 'd3-time-format'; +import { LineChart, XAxis, YAxis, Line, Tooltip } from 'recharts'; import { VIEWERS_OVER_TIME, fetchData } from '../utils/apis'; @@ -10,13 +12,10 @@ export default function ViewersOverTime() { const getInfo = async () => { try { const result = await fetchData(VIEWERS_OVER_TIME); - console.log("viewers result", result) - setViewerInfo(result); } catch (error) { console.log("==== error", error) - // setViewerInfo({ ...viewerInfo, message: error.message }); } }; @@ -32,19 +31,25 @@ export default function ViewersOverTime() { } }, []); + const timeFormatter = (tick) => {return timeFormat('%H:%M:%S')(new Date(tick));}; + - const formattedData = viewerInfo.map(viewer => ({ - x: (new Date(viewer.time)).toLocaleTimeString(), - y: viewer.value, - })); return ( -
+

Viewers over time

Time on X axis, # Viewer on Y

- {JSON.stringify(formattedData)} + {JSON.stringify(viewerInfo)}
+ + + + + + + +
); } diff --git a/web/pages/utils/apis.ts b/web/pages/utils/apis.ts index 891ad6b64..92904db25 100644 --- a/web/pages/utils/apis.ts +++ b/web/pages/utils/apis.ts @@ -46,17 +46,12 @@ export async function fetchData(url) { mode: 'cors', credentials: 'include', }); - // waits until the request completes... - // console.log(response); - if (!response.ok) { - console.log(response) const message = `An error has occured: ${response.status}`; throw new Error(message); } const json = await response.json(); - console.log(json) return json; } catch (error) { console.log(error) diff --git a/web/yarn.lock b/web/yarn.lock index f3a35f681..b64975dc9 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -2458,6 +2458,11 @@ d3-array@^1.2.0: resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f" integrity sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw== +d3-array@^2.3.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-2.8.0.tgz#f76e10ad47f1f4f75f33db5fc322eb9ffde5ef23" + integrity sha512-6V272gsOeg7+9pTW1jSYOR1QE37g95I3my1hBmY+vOUNHRrk9yt4OTz/gK7PMkVAVDrYYq4mq3grTiZ8iJdNIw== + d3-collection@1: version "1.0.7" resolved "https://registry.yarnpkg.com/d3-collection/-/d3-collection-1.0.7.tgz#349bd2aa9977db071091c13144d5e4f16b5b310e" @@ -2468,11 +2473,21 @@ d3-color@1: resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-1.4.1.tgz#c52002bf8846ada4424d55d97982fef26eb3bc8a" integrity sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q== +"d3-color@1 - 2": + version "2.0.0" + resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-2.0.0.tgz#8d625cab42ed9b8f601a1760a389f7ea9189d62e" + integrity sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ== + d3-format@1: version "1.4.5" resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.4.5.tgz#374f2ba1320e3717eb74a9356c67daee17a7edb4" integrity sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ== +"d3-format@1 - 2": + version "2.0.0" + resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-2.0.0.tgz#a10bcc0f986c372b729ba447382413aabf5b0767" + integrity sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA== + d3-interpolate@1, d3-interpolate@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-1.4.0.tgz#526e79e2d80daa383f9e0c1c1c7dcc0f0583e987" @@ -2480,6 +2495,13 @@ d3-interpolate@1, d3-interpolate@^1.3.0: dependencies: d3-color "1" +"d3-interpolate@1.2.0 - 2": + version "2.0.1" + resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-2.0.1.tgz#98be499cfb8a3b94d4ff616900501a64abc91163" + integrity sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ== + dependencies: + d3-color "1 - 2" + d3-path@1: version "1.0.9" resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.9.tgz#48c050bb1fe8c262493a8caf5524e3e9591701cf" @@ -2497,6 +2519,17 @@ d3-scale@^2.1.0: d3-time "1" d3-time-format "2" +d3-scale@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-3.2.3.tgz#be380f57f1f61d4ff2e6cbb65a40593a51649cfd" + integrity sha512-8E37oWEmEzj57bHcnjPVOBS3n4jqakOeuv1EDdQSiSrYnMCBdMd3nc4HtKk7uia8DUHcY/CGuJ42xxgtEYrX0g== + dependencies: + d3-array "^2.3.0" + d3-format "1 - 2" + d3-interpolate "1.2.0 - 2" + d3-time "1 - 2" + d3-time-format "2 - 3" + d3-shape@^1.2.0: version "1.3.7" resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.3.7.tgz#df63801be07bc986bc54f63789b4fe502992b5d7" @@ -2511,11 +2544,23 @@ d3-time-format@2: dependencies: d3-time "1" +"d3-time-format@2 - 3", d3-time-format@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-3.0.0.tgz#df8056c83659e01f20ac5da5fdeae7c08d5f1bb6" + integrity sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag== + dependencies: + d3-time "1 - 2" + d3-time@1: version "1.1.0" resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.1.0.tgz#b1e19d307dae9c900b7e5b25ffc5dcc249a8a0f1" integrity sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA== +"d3-time@1 - 2": + version "2.0.0" + resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-2.0.0.tgz#ad7c127d17c67bd57a4c61f3eaecb81108b1e0ab" + integrity sha512-2mvhstTFcMvwStWd9Tj3e6CEqtOivtD8AUiHT8ido/xmzrI9ijrUUihZ6nHuf/vsScRBonagOdj0Vv+SEL5G3Q== + d@1, d@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" From 81e25d3540873570d4506a8ae55d5e0926fa3886 Mon Sep 17 00:00:00 2001 From: Ginger Wong Date: Wed, 21 Oct 2020 01:19:29 -0700 Subject: [PATCH 11/14] tables --- web/pages/components/connected-clients.tsx | 51 ++++++++++++++++----- web/pages/components/viewer-info.tsx | 43 ++++++++++++------ web/pages/home.tsx | 52 +++++++++++++++------- 3 files changed, 108 insertions(+), 38 deletions(-) diff --git a/web/pages/components/connected-clients.tsx b/web/pages/components/connected-clients.tsx index 82db5091d..70b913491 100644 --- a/web/pages/components/connected-clients.tsx +++ b/web/pages/components/connected-clients.tsx @@ -1,4 +1,6 @@ import React, { useState, useEffect } from 'react'; +import { Table } from 'antd'; + import { CONNECTED_CLIENTS, fetchData, FETCH_INTERVAL } from '../utils/apis'; export default function HardwareInfo() { @@ -16,12 +18,10 @@ geo data looks like this const getInfo = async () => { try { const result = await fetchData(CONNECTED_CLIENTS); - console.log("================ result", result) - - setClients({ ...result }); + setClients(result); } catch (error) { - setClients({ ...clients, message: error.message }); + console.log("==== error", error) } }; @@ -36,15 +36,46 @@ geo data looks like this clearInterval(getStatusIntervalId); } }, []); - + + const columns = [ + { + title: 'User name', + dataIndex: 'username', + key: 'username', + render: username => username || '-', + sorter: (a, b) => a.username - b.username, + sortDirections: ['descend', 'ascend'], + }, + { + title: 'Messages sent', + dataIndex: 'messageCount', + key: 'messageCount', + sorter: (a, b) => a.messageCount - b.messageCount, + sortDirections: ['descend', 'ascend'], + }, + { + title: 'Connected Time', + dataIndex: 'connectedAt', + key: 'connectedAt', + render: time => (Date.now() - (new Date(time).getTime())) / 1000 / 60, + }, + { + title: 'User Agent', + dataIndex: 'userAgent', + key: 'userAgent', + }, + { + title: 'Location', + dataIndex: 'geo', + key: 'geo', + render: geo => geo && `${geo.regionName}, ${geo.countryCode}`, + }, + ]; + return (

Connected Clients

-

a table of info..

-

who's watching, how long they've been there, have they chatted? where they from?

-
- {JSON.stringify(clients)} -
+ ; ); } diff --git a/web/pages/components/viewer-info.tsx b/web/pages/components/viewer-info.tsx index 9ee630f7c..1446585fd 100644 --- a/web/pages/components/viewer-info.tsx +++ b/web/pages/components/viewer-info.tsx @@ -3,7 +3,6 @@ import {timeFormat} from 'd3-time-format'; import { LineChart, XAxis, YAxis, Line, Tooltip } from 'recharts'; import { VIEWERS_OVER_TIME, fetchData } from '../utils/apis'; - const FETCH_INTERVAL = 5 * 60 * 1000; // 5 mins export default function ViewersOverTime() { @@ -13,7 +12,6 @@ export default function ViewersOverTime() { try { const result = await fetchData(VIEWERS_OVER_TIME); setViewerInfo(result); - } catch (error) { console.log("==== error", error) } @@ -33,22 +31,41 @@ export default function ViewersOverTime() { const timeFormatter = (tick) => {return timeFormat('%H:%M:%S')(new Date(tick));}; + const CustomizedTooltip = (props) => { + const { active, payload, label } = props; + if (active) { + const numViewers = payload && payload[0] && payload[0].value; + const time = timeFormatter(label); + const message = `${numViewers} viewer(s) at ${time}`; + return ( +
+

{message}

+
+ ); + } + return null; + }; return ( -
-

Viewers over time

-

Time on X axis, # Viewer on Y

-
- {JSON.stringify(viewerInfo)} +
+

Current Viewers

+
+ + + + } + /> + +
- - - - - -
); diff --git a/web/pages/home.tsx b/web/pages/home.tsx index ea76aaa52..97f823a4c 100644 --- a/web/pages/home.tsx +++ b/web/pages/home.tsx @@ -1,4 +1,6 @@ import React, { useState, useEffect } from 'react'; +import { Layout } from 'antd'; + import BroadcastInfo from './components/broadcast-info'; import HardwareInfo from './components/hardware-info'; @@ -9,35 +11,55 @@ import ConnectedClients from './components/connected-clients'; export default function HomeView(props) { const { broadcastActive, broadcaster, message } = props; + const { Header, Footer, Content } = Layout; + const broadcastDetails = broadcastActive ? ( <> {/* */} - {/* - */} + + {/* */} ) : null; const disconnectButton = broadcastActive ? : null; return ( -
-

- Status: {broadcastActive ? 'on' : 'off'} -

+ +
+
logo
+ {/* + nav 1 + nav 2 + nav 3 + */} +
+ +
+

+ Status: {broadcastActive ? 'on' : 'off'} +

-

Utilities

-

(these dont do anything yet)

+

Utilities

+

(these dont do anything yet)

- {disconnectButton} - - + {disconnectButton} + + -
-
+
+
+ + {broadcastDetails} + + +
+
+ +
+ + - {broadcastDetails} -
); } From 2b278c45e17063be29791676d0bcd6695746b194 Mon Sep 17 00:00:00 2001 From: Ginger Wong Date: Thu, 22 Oct 2020 01:03:15 -0700 Subject: [PATCH 12/14] adding a nicer layout frame, setting up for pages --- web/pages/_app.tsx | 2 + web/pages/components/connected-clients.tsx | 6 +-- web/pages/home.tsx | 63 ++-------------------- web/pages/index2.tsx | 7 ++- web/pages/utils/apis.ts | 1 - web/styles/globals.scss | 13 ++++- 6 files changed, 26 insertions(+), 66 deletions(-) diff --git a/web/pages/_app.tsx b/web/pages/_app.tsx index 22af59f11..f1a4e0eb9 100644 --- a/web/pages/_app.tsx +++ b/web/pages/_app.tsx @@ -4,6 +4,8 @@ import 'antd/dist/antd.dark.css'; import 'antd/dist/antd.compact.css'; +import "../styles/globals.scss"; + import { AppProps } from 'next/app' function App({ Component, pageProps }: AppProps) { diff --git a/web/pages/components/connected-clients.tsx b/web/pages/components/connected-clients.tsx index 70b913491..5a3e8d29b 100644 --- a/web/pages/components/connected-clients.tsx +++ b/web/pages/components/connected-clients.tsx @@ -3,9 +3,6 @@ import { Table } from 'antd'; import { CONNECTED_CLIENTS, fetchData, FETCH_INTERVAL } from '../utils/apis'; -export default function HardwareInfo() { - const [clients, setClients] = useState({}); - /* geo data looks like this "geo": { @@ -15,6 +12,8 @@ geo data looks like this } */ +export default function HardwareInfo() { + const [clients, setClients] = useState([]); const getInfo = async () => { try { const result = await fetchData(CONNECTED_CLIENTS); @@ -72,6 +71,7 @@ geo data looks like this }, ]; + console.log({clients}) return (

Connected Clients

diff --git a/web/pages/home.tsx b/web/pages/home.tsx index 97f823a4c..1609d3893 100644 --- a/web/pages/home.tsx +++ b/web/pages/home.tsx @@ -1,65 +1,12 @@ -import React, { useState, useEffect } from 'react'; -import { Layout } from 'antd'; +import React from 'react'; +import adminStyles from './components/styles.module.css'; -import BroadcastInfo from './components/broadcast-info'; -import HardwareInfo from './components/hardware-info'; -import ViewerInfo from './components/viewer-info'; -import ServerConfig from './components/server-config'; -import ConnectedClients from './components/connected-clients'; export default function HomeView(props) { - const { broadcastActive, broadcaster, message } = props; - - const { Header, Footer, Content } = Layout; - - const broadcastDetails = broadcastActive ? ( - <> - {/* - */} - - - {/* */} - - ) : null; - - const disconnectButton = broadcastActive ? : null; - return ( - -
-
logo
- {/* - nav 1 - nav 2 - nav 3 - */} -
- -
-

- Status: {broadcastActive ? 'on' : 'off'} -

- -

Utilities

-

(these dont do anything yet)

- - {disconnectButton} - - - -
-
- - {broadcastDetails} - - -
-
- -
- - - +
+ < pick something +
); } diff --git a/web/pages/index2.tsx b/web/pages/index2.tsx index e085ba74e..fdb9060ae 100644 --- a/web/pages/index2.tsx +++ b/web/pages/index2.tsx @@ -1,6 +1,7 @@ import React, { useState, useEffect } from 'react'; import { BROADCASTER, fetchData, FETCH_INTERVAL } from './utils/apis'; -import Main from './home'; +import MainLayout from './components/main-layout'; +import Home from './home'; export default function Admin() { const [broadcasterStatus, setBroadcasterStatus] = useState({}); @@ -35,6 +36,8 @@ export default function Admin() { return ( -
+ + + ); } diff --git a/web/pages/utils/apis.ts b/web/pages/utils/apis.ts index 92904db25..898242ddc 100644 --- a/web/pages/utils/apis.ts +++ b/web/pages/utils/apis.ts @@ -50,7 +50,6 @@ export async function fetchData(url) { const message = `An error has occured: ${response.status}`; throw new Error(message); } - const json = await response.json(); return json; } catch (error) { diff --git a/web/styles/globals.scss b/web/styles/globals.scss index e5e2dcc23..00a0ff23f 100644 --- a/web/styles/globals.scss +++ b/web/styles/globals.scss @@ -1,16 +1,25 @@ +$owncast-purple: rgba(90,103,216,1);; + html, body { padding: 0; margin: 0; - font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, - Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; + font-family: system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"; + + font-size: 16px; } a { color: inherit; text-decoration: none; + color: rgba(90,103,216,1); } * { box-sizing: border-box; } + + +.owncast-layout .ant-menu-dark.ant-menu-dark:not(.ant-menu-horizontal) .ant-menu-item-selected { + background-color: $owncast-purple; +} From a0628567267d200fca579a5511a33663e9c4a297 Mon Sep 17 00:00:00 2001 From: Ginger Wong Date: Thu, 22 Oct 2020 16:18:18 -0700 Subject: [PATCH 13/14] a bit of refactor, use context for overall broacast status; move files around for routing --- web/favicon.ico | Bin 0 -> 3991 bytes web/package.json | 1 + web/pages/_app.tsx | 20 +-- web/pages/broadcast-info.tsx | 18 +++ web/pages/components/broadcast-info.tsx | 15 --- web/pages/components/logo.tsx | 85 +++++++++++++ web/pages/components/main-layout.tsx | 119 ++++++++++++++++++ .../{components => }/connected-clients.tsx | 3 +- web/pages/{components => }/hardware-info.tsx | 2 +- web/pages/home.tsx | 12 -- web/pages/index2.tsx | 45 +------ web/pages/update-server-config.tsx | 40 ++++++ web/pages/utils/broadcast-status-context.tsx | 51 ++++++++ web/pages/{components => }/viewer-info.tsx | 5 +- web/styles/styles.module.css | 69 ++++++++++ 15 files changed, 406 insertions(+), 79 deletions(-) create mode 100644 web/favicon.ico create mode 100644 web/pages/broadcast-info.tsx delete mode 100644 web/pages/components/broadcast-info.tsx create mode 100644 web/pages/components/logo.tsx create mode 100644 web/pages/components/main-layout.tsx rename web/pages/{components => }/connected-clients.tsx (94%) rename web/pages/{components => }/hardware-info.tsx (93%) delete mode 100644 web/pages/home.tsx create mode 100644 web/pages/update-server-config.tsx create mode 100644 web/pages/utils/broadcast-status-context.tsx rename web/pages/{components => }/viewer-info.tsx (96%) create mode 100644 web/styles/styles.module.css diff --git a/web/favicon.ico b/web/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..7a859e7ee041c7be65e53c2aa45b1cac0b530aa8 GIT binary patch literal 3991 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4mJh`hH$2z?FHY5gN(z}Nwo2iqz6QPp&Z!xh9#uuD!Bu`C$yM3OmMKd1b_zBXRu#Dg zxv3?I3Kh9IdBs*0wn|`gt@4VkK*IV;3ScEA*|tg$M@9GsC^+XAr7D=|8R#Y(7#Jy- zTk08_nV6Uv=qMN&7#ZjrnCcrE=^C0@8JJiZnkztolAVH0QA(Oskc%7CuA-DQTcwPW zk^(Dz{qpj1y>er{{GxPyLrY6beFGzXBO~3Slr-Jq%Dj@q3f;V7Wta&rsl~}fnFS@8 z`FRQ;6BCp2OG|8(l%U2|A zTTylv&Z=GdG^m-8*Y$XH}?+p^o6ur)qi{S{*JY^$eJqH=n=r{?DI9 z2hP0cshIb?Hf_fL|L1@1`&@tecP;zDjmgI+%$n7eCe_#y;AC)czQXhR^=eZDK5=a4 zET5gc@!#Ly&T}SBYAStw&C;s9MZi_Ur$eztu!e(4`}=Ipr!6v0QV%s0=PoEtDV*rR zvT^d{$;#({3EorkQ7YN=*mBtn{r-C`t}Qx;>N#$6F8#)FFh%^9<__-tFH#R>S+{OC zv-(&Z`|Nqy#^;H%xj0yuI9i=NRL%qmcv~FSzs7aeKI&ufX49nDC3ynfM^u{M+KNT* z7Lbza3RG@8oMZO*#Ka}8*EeknyRqy3qifr08IynexVg;MoAdRK-k!F@&%Zsm(|bS1 z_S)2fMd|I+?dF&l9hK_5!TH(T*CFhm>u-?>yLTSEe?NXp^7DRak00f4@1FBy7E5^e zLUh7ul?#%u?raZt5z#aewGK8*Jo?T;qK9p@^z5py7qY_BD_=}EuAB4l<*V#1zj;?& z&ANC^e%s%Qx4*s?e&e!ND-)a67tg(Q+Mb}qRs5bhESx7*)Ocrj?Vq0H{K#nbXO-9+ zU-Q;(3yTX~J;S43>TS@2XKSPHUv9s9sGYUs*c`$51)JEm99H8lpRr)QP*TYJogNl@ z1yi|hYd(B3mDz_)^kHoEoC?LnF6DVYzCCy<(5V`b$#X%%M{MCGDaGQ#!=Dv5_FKOd ziCcEOidn~SZHdc|3k~aDNZCnr~|zUdq)xko3W=dhyx6 zf|o0m&P{=mDzv+F}(SID}&GqBc%nJ)I9_r4R zV9BzxQtE|CT9=Jb(FGl$D4zW91`@qeK?jd~=44!wn)c-G*}@b}wZ~?M_8#-InHhd) z;lro@Y_vj+G)&xHWOnz*|6`avsVd>}MLCPo$Hg;ZR4!Q0w3JxF6!PM9K*+?GCxZ6v zS;M6Vo2EU%dPS~TH|!JVWzs(LD7_P1`v*fcE=WHe>s{kP*^sPb~tMNYvCb0-T# zO`Q3APvP_F>NnRH#67E$mq>cK?!g3sJ)d5!Ued}@UQ|4>>{I!bYgZzkJzHmY;o`h0 zqUj5_eCcI@%V%RXz%9aq#@vKqzwg7{PB-R79P?vCkI)~%|a6_wf-EZ7!v_3#;u6}i?t(uP9u`S(4$dh(2B$LTao6Il_GX1-HQz)(tU zrcBjJVK0&JiF0=@wR~YddFRv#{~ulbv8uhD{h(}6kwyLgX&qg?uDxEY;^N{u@&9F& zet*j@*ne!z+Ru!ohZlKieRg%2ZXW2p)BU;1p{ZN?HQYnY+nMIId~@2zkUz;dJ3D*j zgo#eiUUkV$oERbcpR?^-=do|R_YYn5?K^)h-{Ew_0ru~&-xcN`V5oJr?~3DDSg!Ep z+_@dKU)e=c<+IKyt_nn?U z;z_+K8*~4=SOP^=bJgn|%qtsg0&-sS?TzbieSh{~>*wbm|LwOs6n=YK;-~7*1!iwWqFCD{@U$t?N#x$!7U3GD7d(kIC%U{`0@Ma!LxUHm1Z4IxUhKDE-6)2 z)hQoO#;?2YP#AdfvBre+A_+5>PkQio#qOz7r{36Esm!h~FMn!P&=j#-YANeP+S>W+ zWu4o2+$!1)^cERLtzE9L@M6}&tFJn;UMHGJzMNdAo+{Gi_2<14+qXCOx|?=~Jr5Ts zn#t6z~+@}@TPC+$3?v3y5S)AdRI zl00ndt{%$pnZNJi3zxd>RZqoFoZOe2S*2DyafbQ)EyqI-oSkd5WxM&QF0O@(Ww%Hz zIO($Q|37OMmMw0VE-v=)xY55leEp(1BI&!&z35!NoPA#PKg%9jbFSPbCJWXb`&v&P z(R}&vWuNC{b%nZ{T%V4r*{Y~*{%I#|o3!@T`uvj0s-$C+QadC~Bv!rB((st@b$(sT zYsqQWX?Aw^RB9N!GOnke>2NOH$~A3MZDOLJk&)iR+r04;ckVRFD9bd7V%f&oFn|Ai z)nKbX1-1p#>Q%#z_po+pjS4@regn1%NyJC?QaEj z#O^NReSYAYTV$qW$dSz~PKlGl%&Mh%#Lhf_bC_$xzdvEoTon`6c72UXiQmZ+8Y=pW zU#6q!4*NFC%y&$0_7-q$GzbD+fQ(2LIEhk8!xBp6M zbL)lA&-Dr(95VXZd?%KVb0&9n*usD!zT8BKiknyZv)*mG_c*9}Qq;-2`vs+L$;r;E zZ2P_Y#k<%ich5M5l$bajI+SB~x|L=I*>ZEd10iS}pi0?D@~>`#O7V(NiyXZhwEH{KWHzFEj6K z`~AGrIljL3^J1|?${xp24xRwe?xKzGvUwulsxTnPR+OnVB1(bl1h?<4vt;`T6oomM?#N;^E=G z6L~ML?S0*T*nRJ|wx6x4QbG39bT-CiYz~^ZRWvoEapAierp^4C{=zxE5$RRcI;%KY zuAQFp<448q=SOrlZn$yAr-hCCg}#v3W{1xrt5z%3GmWdVr%Us=H33UB6;GR zUmViECUZ1T%syPaE^liryY`yeM;^MT^uMX@PhKyy=%?QO#ag?$=J^`^n{;G;wWSKn z>DUtgv)rxc@S{dsjWjPJiprJ(qsg@Wx$`>Hhlmw)lVX1cthc+auTnbLWD( N%AT%%F6*2Ung9`H6kY%T literal 0 HcmV?d00001 diff --git a/web/package.json b/web/package.json index bf39b247f..834ef4456 100644 --- a/web/package.json +++ b/web/package.json @@ -10,6 +10,7 @@ "dependencies": { "@ant-design/icons": "^4.2.2", "antd": "^4.6.6", + "classnames": "^2.2.6", "d3-scale": "^3.2.3", "d3-time-format": "^3.0.0", "next": "9.5.3", diff --git a/web/pages/_app.tsx b/web/pages/_app.tsx index f1a4e0eb9..958b72559 100644 --- a/web/pages/_app.tsx +++ b/web/pages/_app.tsx @@ -1,15 +1,21 @@ -// import 'antd/dist/antd.css'; -// import '../styles/globals.scss' - import 'antd/dist/antd.dark.css'; import 'antd/dist/antd.compact.css'; - import "../styles/globals.scss"; -import { AppProps } from 'next/app' +import { AppProps } from 'next/app'; +import BroadcastStatusProvider from './utils/broadcast-status-context'; +import MainLayout from './components/main-layout'; + function App({ Component, pageProps }: AppProps) { - return + return ( + + + + + + + ) } -export default App \ No newline at end of file +export default App; \ No newline at end of file diff --git a/web/pages/broadcast-info.tsx b/web/pages/broadcast-info.tsx new file mode 100644 index 000000000..465b48de5 --- /dev/null +++ b/web/pages/broadcast-info.tsx @@ -0,0 +1,18 @@ +import React, { useContext } from 'react'; +import { BroadcastStatusContext } from './utils/broadcast-status-context'; + + +export default function BroadcastInfo() { + const context = useContext(BroadcastStatusContext); + const { broadcaster } = context || {}; + const { remoteAddr, time, streamDetails } = broadcaster || {}; + + return ( +
+

Broadcast Info

+

Remote Address: {remoteAddr}

+

Time: {(new Date(time)).toLocaleTimeString()}

+

Stream Details: {JSON.stringify(streamDetails)}

+
+ ); +} diff --git a/web/pages/components/broadcast-info.tsx b/web/pages/components/broadcast-info.tsx deleted file mode 100644 index bf68c888d..000000000 --- a/web/pages/components/broadcast-info.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React, { useState, useEffect } from 'react'; - - -export default function BroadcastInfo(props) { -const { remoteAddr, streamDetails, time } = props; - - return ( -
-

Broadcast Info

-

Remote Address: {remoteAddr}

-

Time: {(new Date(time)).toLocaleTimeString()}

-

Stream Details: {JSON.stringify(streamDetails)}

-
- ); -} diff --git a/web/pages/components/logo.tsx b/web/pages/components/logo.tsx new file mode 100644 index 000000000..a6a814185 --- /dev/null +++ b/web/pages/components/logo.tsx @@ -0,0 +1,85 @@ +import React from 'react'; +import adminStyles from '../../styles/styles.module.css'; + +export default function Logo() { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} \ No newline at end of file diff --git a/web/pages/components/main-layout.tsx b/web/pages/components/main-layout.tsx new file mode 100644 index 000000000..72bdd59de --- /dev/null +++ b/web/pages/components/main-layout.tsx @@ -0,0 +1,119 @@ +import React, { useContext } from 'react'; +import PropTypes from 'prop-types'; +import Link from 'next/link'; +import { useRouter } from 'next/router'; +import { Layout, Menu } from 'antd'; +import { + SettingOutlined, + HomeOutlined, + LineChartOutlined, + CloseCircleOutlined, + PlayCircleFilled, +} from '@ant-design/icons'; +import classNames from 'classNames'; + + +import OwncastLogo from './logo'; +import { BroadcastStatusContext } from '../utils/broadcast-status-context'; + +import adminStyles from '../../styles/styles.module.css'; + +export default function MainLayout(props) { + const { children } = props; + + const context = useContext(BroadcastStatusContext); + const { broadcastActive } = context || {}; + + const router = useRouter(); + const { route } = router || {}; + + const { Header, Footer, Content, Sider } = Layout; + const { SubMenu } = Menu; + + const statusMessage = broadcastActive ? + 'Online' : 'Offline'; + + const appClass = classNames({ + 'owncast-layout': true, + [adminStyles.online]: broadcastActive, + }) + return ( + + + +

+ + + + Owncast Admin +

+ }> + Home + + + } title="Stream Details"> + + Hardware + + + Broadcaster Info + + + Viewers + + + Connected Clients + + { broadcastActive ? ( + }> + Disconnect Stream... + + ) : null} + + + } title="Utilities"> + + Update Server Configuration + + + Change Stream Key + + +
+
+ + +
+
+ + + + + {statusMessage} + +
+
+ + {children} + + + +
+
+ ); +} + +MainLayout.propTypes = { + children: PropTypes.element.isRequired, +}; \ No newline at end of file diff --git a/web/pages/components/connected-clients.tsx b/web/pages/connected-clients.tsx similarity index 94% rename from web/pages/components/connected-clients.tsx rename to web/pages/connected-clients.tsx index 5a3e8d29b..312cbc9cc 100644 --- a/web/pages/components/connected-clients.tsx +++ b/web/pages/connected-clients.tsx @@ -1,7 +1,7 @@ import React, { useState, useEffect } from 'react'; import { Table } from 'antd'; -import { CONNECTED_CLIENTS, fetchData, FETCH_INTERVAL } from '../utils/apis'; +import { CONNECTED_CLIENTS, fetchData, FETCH_INTERVAL } from './utils/apis'; /* geo data looks like this @@ -71,7 +71,6 @@ export default function HardwareInfo() { }, ]; - console.log({clients}) return (

Connected Clients

diff --git a/web/pages/components/hardware-info.tsx b/web/pages/hardware-info.tsx similarity index 93% rename from web/pages/components/hardware-info.tsx rename to web/pages/hardware-info.tsx index 919489c2e..d92876499 100644 --- a/web/pages/components/hardware-info.tsx +++ b/web/pages/hardware-info.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react'; -import { HARDWARE_STATS, fetchData, FETCH_INTERVAL } from '../utils/apis'; +import { HARDWARE_STATS, fetchData, FETCH_INTERVAL } from './utils/apis'; export default function HardwareInfo() { const [hardwareStatus, setHardwareStatus] = useState({}); diff --git a/web/pages/home.tsx b/web/pages/home.tsx deleted file mode 100644 index 1609d3893..000000000 --- a/web/pages/home.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; - -import adminStyles from './components/styles.module.css'; - - -export default function HomeView(props) { - return ( -
- < pick something -
- ); -} diff --git a/web/pages/index2.tsx b/web/pages/index2.tsx index fdb9060ae..58dc825d7 100644 --- a/web/pages/index2.tsx +++ b/web/pages/index2.tsx @@ -1,43 +1,10 @@ -import React, { useState, useEffect } from 'react'; -import { BROADCASTER, fetchData, FETCH_INTERVAL } from './utils/apis'; -import MainLayout from './components/main-layout'; -import Home from './home'; +import React from 'react'; -export default function Admin() { - const [broadcasterStatus, setBroadcasterStatus] = useState({}); - const [count, setCount] = useState(0); - - const getBroadcastStatus = async () => { - try { - const result = await fetchData(BROADCASTER); - const broadcastActive = !!result.broadcaster; - - console.log("====",{count, result}) - - setBroadcasterStatus({ ...result, broadcastActive }); - setCount(c => c + 1); - - } catch (error) { - setBroadcasterStatus({ ...broadcasterStatus, message: error.message }); - } - }; - - useEffect(() => { - let getStatusIntervalId = null; - - getBroadcastStatus(); - getStatusIntervalId = setInterval(getBroadcastStatus, FETCH_INTERVAL); - - // returned function will be called on component unmount - return () => { - clearInterval(getStatusIntervalId); - } - }, []) - - +export default function AdminHome() { return ( - - - +
+ < pick something
+ Home view. pretty pictures. Rainbows. Kittens. +
); } diff --git a/web/pages/update-server-config.tsx b/web/pages/update-server-config.tsx new file mode 100644 index 000000000..7aa101dd0 --- /dev/null +++ b/web/pages/update-server-config.tsx @@ -0,0 +1,40 @@ +import React, { useState, useEffect } from 'react'; +import { SERVER_CONFIG, fetchData, FETCH_INTERVAL } from './utils/apis'; + +export default function ServerConfig() { + const [clients, setClients] = useState({}); + + const getInfo = async () => { + try { + const result = await fetchData(SERVER_CONFIG); + console.log("viewers result", result) + + setClients({ ...result }); + + } catch (error) { + setClients({ ...clients, message: error.message }); + } + }; + + useEffect(() => { + let getStatusIntervalId = null; + + getInfo(); + getStatusIntervalId = setInterval(getInfo, FETCH_INTERVAL); + + // returned function will be called on component unmount + return () => { + clearInterval(getStatusIntervalId); + } + }, []); + + return ( +
+

Server Config

+

Display this data all pretty, most things will be editable in the future, not now.

+
+ {JSON.stringify(clients)} +
+
+ ); +} diff --git a/web/pages/utils/broadcast-status-context.tsx b/web/pages/utils/broadcast-status-context.tsx new file mode 100644 index 000000000..86e595b24 --- /dev/null +++ b/web/pages/utils/broadcast-status-context.tsx @@ -0,0 +1,51 @@ +import React, { useState, useEffect } from 'react'; +import PropTypes from 'prop-types'; + +import { BROADCASTER, fetchData, FETCH_INTERVAL } from './apis'; + +const initialState = { + broadcastActive: false, + message: '', + broadcaster: null, +}; + +export const BroadcastStatusContext = React.createContext(initialState); + +const BroadcastStatusProvider = ({ children }) => { + const [broadcasterStatus, setBroadcasterStatus] = useState(initialState); + + const getBroadcastStatus = async () => { + try { + const result = await fetchData(BROADCASTER); + const broadcastActive = !!result.broadcaster; + setBroadcasterStatus({ ...result, broadcastActive }); + + } catch (error) { + setBroadcasterStatus({ ...broadcasterStatus, message: error.message }); + } + }; + + useEffect(() => { + let getStatusIntervalId = null; + + getBroadcastStatus(); + getStatusIntervalId = setInterval(getBroadcastStatus, FETCH_INTERVAL); + + // returned function will be called on component unmount + return () => { + clearInterval(getStatusIntervalId); + } + }, []) + + return ( + + {children} + + ); +} + +BroadcastStatusProvider.propTypes = { + children: PropTypes.element.isRequired, +}; + +export default BroadcastStatusProvider; \ No newline at end of file diff --git a/web/pages/components/viewer-info.tsx b/web/pages/viewer-info.tsx similarity index 96% rename from web/pages/components/viewer-info.tsx rename to web/pages/viewer-info.tsx index 1446585fd..e63806a03 100644 --- a/web/pages/components/viewer-info.tsx +++ b/web/pages/viewer-info.tsx @@ -1,7 +1,8 @@ import React, { useState, useEffect } from 'react'; import {timeFormat} from 'd3-time-format'; import { LineChart, XAxis, YAxis, Line, Tooltip } from 'recharts'; -import { VIEWERS_OVER_TIME, fetchData } from '../utils/apis'; + +import { VIEWERS_OVER_TIME, fetchData } from './utils/apis'; const FETCH_INTERVAL = 5 * 60 * 1000; // 5 mins @@ -65,8 +66,6 @@ export default function ViewersOverTime() { />
- -
); } diff --git a/web/styles/styles.module.css b/web/styles/styles.module.css new file mode 100644 index 000000000..0b59be3fb --- /dev/null +++ b/web/styles/styles.module.css @@ -0,0 +1,69 @@ + +.logoSVG { + height: 2rem; + width: 2rem; +} + +.owncastTitleContainer { + padding: 1rem; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + +} +.logoContainer { + background-color: #fff; + padding: .35rem; + border-radius: 9999px; +} +.owncastTitle { + display: inline-block; + margin-left: 1rem; + color: rgba(203,213,224, 1); + font-size: 1.15rem; + font-weight: 200; + text-transform: uppercase; + line-height: normal; + letter-spacing: .05em; +} + +.contentMain { + padding: 3em; +} + +.header { + display: flex; + flex-direction: row; + justify-content: flex-end; +} + +.statusIndicatorContainer { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + +} +.statusIcon { + font-size: 1.5rem; +} +.statusIcon svg { + fill: #ccc; +} +.statusLabel { + color: #fff; + text-transform: uppercase; + font-size: .75rem; + display: inline-block; + margin-left: .5rem; + color: #ccc; +} +.online .statusIcon svg { + fill: #52c41a; +} +.online .statusLabel { + color: #52c41a; +} + +/* //844-227-3943 */ \ No newline at end of file From 00fd087fde06138318c1af21049c579e6cde4be4 Mon Sep 17 00:00:00 2001 From: Ginger Wong Date: Thu, 22 Oct 2020 17:16:28 -0700 Subject: [PATCH 14/14] some cleanup --- web/pages/components/main-layout.tsx | 16 ++++++----- web/pages/connected-clients.tsx | 28 ++++++++++++++------ web/pages/hardware-info.tsx | 6 ++++- web/pages/index.tsx | 10 ++++++- web/pages/index2.tsx | 10 ------- web/pages/update-server-config.tsx | 7 ++++- web/pages/utils/broadcast-status-context.tsx | 2 +- web/pages/viewer-info.tsx | 28 +++++++++++++++----- web/styles/styles.module.css | 7 ++--- 9 files changed, 76 insertions(+), 38 deletions(-) delete mode 100644 web/pages/index2.tsx diff --git a/web/pages/components/main-layout.tsx b/web/pages/components/main-layout.tsx index 72bdd59de..1e099cdfc 100644 --- a/web/pages/components/main-layout.tsx +++ b/web/pages/components/main-layout.tsx @@ -9,8 +9,10 @@ import { LineChartOutlined, CloseCircleOutlined, PlayCircleFilled, + StopFilled, + MinusSquareFilled, } from '@ant-design/icons'; -import classNames from 'classNames'; +import classNames from 'classnames'; import OwncastLogo from './logo'; @@ -30,7 +32,9 @@ export default function MainLayout(props) { const { Header, Footer, Content, Sider } = Layout; const { SubMenu } = Menu; - const statusMessage = broadcastActive ? + const statusIcon = broadcastActive ? + : ; + const statusMessage = broadcastActive ? 'Online' : 'Offline'; const appClass = classNames({ @@ -59,7 +63,7 @@ export default function MainLayout(props) { Owncast Admin }> - Home + Home } title="Stream Details"> @@ -96,12 +100,12 @@ export default function MainLayout(props) {
- - - {statusMessage} + + {statusIcon} +
diff --git a/web/pages/connected-clients.tsx b/web/pages/connected-clients.tsx index 312cbc9cc..458e4a78e 100644 --- a/web/pages/connected-clients.tsx +++ b/web/pages/connected-clients.tsx @@ -1,5 +1,6 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useContext } from 'react'; import { Table } from 'antd'; +import { BroadcastStatusContext } from './utils/broadcast-status-context'; import { CONNECTED_CLIENTS, fetchData, FETCH_INTERVAL } from './utils/apis'; @@ -12,13 +13,16 @@ geo data looks like this } */ -export default function HardwareInfo() { +export default function ConnectedClients() { + const context = useContext(BroadcastStatusContext); + const { broadcastActive } = context || {}; + const [clients, setClients] = useState([]); const getInfo = async () => { try { const result = await fetchData(CONNECTED_CLIENTS); + console.log("result",result) setClients(result); - } catch (error) { console.log("==== error", error) } @@ -28,14 +32,22 @@ export default function HardwareInfo() { let getStatusIntervalId = null; getInfo(); - getStatusIntervalId = setInterval(getInfo, FETCH_INTERVAL); - - // returned function will be called on component unmount - return () => { - clearInterval(getStatusIntervalId); + if (broadcastActive) { + getStatusIntervalId = setInterval(getInfo, FETCH_INTERVAL); + // returned function will be called on component unmount + return () => { + clearInterval(getStatusIntervalId); + } } + return () => []; }, []); + if (!clients.length) { + return "no clients"; + } + + // todo - check to see if broadcast active has changed. if so, start polling. + const columns = [ { title: 'User name', diff --git a/web/pages/hardware-info.tsx b/web/pages/hardware-info.tsx index d92876499..f26c0aeee 100644 --- a/web/pages/hardware-info.tsx +++ b/web/pages/hardware-info.tsx @@ -1,7 +1,11 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useContext } from 'react'; import { HARDWARE_STATS, fetchData, FETCH_INTERVAL } from './utils/apis'; +import { BroadcastStatusContext } from './utils/broadcast-status-context'; export default function HardwareInfo() { + const context = useContext(BroadcastStatusContext); + const { broadcastActive } = context || {}; + const [hardwareStatus, setHardwareStatus] = useState({}); const getHardwareStatus = async () => { diff --git a/web/pages/index.tsx b/web/pages/index.tsx index 7284410bf..58cbdaaf9 100644 --- a/web/pages/index.tsx +++ b/web/pages/index.tsx @@ -1,11 +1,19 @@ +import React from 'react'; import { Card, Alert, Statistic, Row, Col } from "antd"; import { LikeOutlined } from "@ant-design/icons"; const { Meta } = Card; -export default function Home() { +export default function AdminHome() { return (
+
+ < pick something
+ Home view. pretty pictures. Rainbows. Kittens. +
+ +

+ - < pick something
- Home view. pretty pictures. Rainbows. Kittens. -
- ); -} diff --git a/web/pages/update-server-config.tsx b/web/pages/update-server-config.tsx index 7aa101dd0..3abc52178 100644 --- a/web/pages/update-server-config.tsx +++ b/web/pages/update-server-config.tsx @@ -1,7 +1,12 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useContext } from 'react'; import { SERVER_CONFIG, fetchData, FETCH_INTERVAL } from './utils/apis'; +import { BroadcastStatusContext } from './utils/broadcast-status-context'; export default function ServerConfig() { + const context = useContext(BroadcastStatusContext); + const { broadcastActive } = context || {}; + + const [clients, setClients] = useState({}); const getInfo = async () => { diff --git a/web/pages/utils/broadcast-status-context.tsx b/web/pages/utils/broadcast-status-context.tsx index 86e595b24..309c2152d 100644 --- a/web/pages/utils/broadcast-status-context.tsx +++ b/web/pages/utils/broadcast-status-context.tsx @@ -17,7 +17,7 @@ const BroadcastStatusProvider = ({ children }) => { const getBroadcastStatus = async () => { try { const result = await fetchData(BROADCASTER); - const broadcastActive = !!result.broadcaster; + const broadcastActive = !!result.broadcaster || result.success; setBroadcasterStatus({ ...result, broadcastActive }); } catch (error) { diff --git a/web/pages/viewer-info.tsx b/web/pages/viewer-info.tsx index e63806a03..c545506ce 100644 --- a/web/pages/viewer-info.tsx +++ b/web/pages/viewer-info.tsx @@ -1,12 +1,16 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useContext } from 'react'; import {timeFormat} from 'd3-time-format'; import { LineChart, XAxis, YAxis, Line, Tooltip } from 'recharts'; +import { BroadcastStatusContext } from './utils/broadcast-status-context'; import { VIEWERS_OVER_TIME, fetchData } from './utils/apis'; const FETCH_INTERVAL = 5 * 60 * 1000; // 5 mins export default function ViewersOverTime() { + const context = useContext(BroadcastStatusContext); + const { broadcastActive } = context || {}; + const [viewerInfo, setViewerInfo] = useState([]); const getInfo = async () => { @@ -17,18 +21,28 @@ export default function ViewersOverTime() { console.log("==== error", error) } }; - + useEffect(() => { let getStatusIntervalId = null; getInfo(); - getStatusIntervalId = setInterval(getInfo, FETCH_INTERVAL); - - // returned function will be called on component unmount - return () => { - clearInterval(getStatusIntervalId); + if (broadcastActive) { + getStatusIntervalId = setInterval(getInfo, FETCH_INTERVAL); + // returned function will be called on component unmount + return () => { + clearInterval(getStatusIntervalId); + } } + return () => []; }, []); + + + // todo - check to see if broadcast active has changed. if so, start polling. + + + if (!viewerInfo.length) { + return "no info"; + } const timeFormatter = (tick) => {return timeFormat('%H:%M:%S')(new Date(tick));}; diff --git a/web/styles/styles.module.css b/web/styles/styles.module.css index 0b59be3fb..5c1fe19ed 100644 --- a/web/styles/styles.module.css +++ b/web/styles/styles.module.css @@ -36,6 +36,7 @@ display: flex; flex-direction: row; justify-content: flex-end; + padding-right: 1rem; } .statusIndicatorContainer { @@ -49,15 +50,15 @@ font-size: 1.5rem; } .statusIcon svg { - fill: #ccc; + fill: #999; } .statusLabel { color: #fff; text-transform: uppercase; font-size: .75rem; display: inline-block; - margin-left: .5rem; - color: #ccc; + margin-right: .5rem; + color: #999; } .online .statusIcon svg { fill: #52c41a;