diff --git a/package.json b/package.json index 9318fca..c6c446a 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "react-intl": "^6.4.4", "react-router-dom": "^6.13.0", "react-tag-input-component": "^2.0.2", + "recharts": "^2.9.3", "semantic-sdp": "^3.26.3", "usehooks-ts": "^2.9.1", "web-vitals": "^2.1.0", diff --git a/src/hooks/live-chat.tsx b/src/hooks/live-chat.tsx index 5bb658a..b76354e 100644 --- a/src/hooks/live-chat.tsx +++ b/src/hooks/live-chat.tsx @@ -4,7 +4,7 @@ import { unixNow } from "@snort/shared"; import { useMemo } from "react"; import { LIVE_STREAM_CHAT, WEEK } from "const"; -export function useLiveChatFeed(link: NostrLink, eZaps?: Array) { +export function useLiveChatFeed(link: NostrLink, eZaps?: Array, limit = 100) { const since = useMemo(() => unixNow() - WEEK, [link.id]); const sub = useMemo(() => { const rb = new RequestBuilder(`live:${link.id}:${link.author}`); @@ -12,7 +12,7 @@ export function useLiveChatFeed(link: NostrLink, eZaps?: Array) { leaveOpen: true, }); const aTag = `${link.kind}:${link.author}:${link.id}`; - rb.withFilter().kinds([LIVE_STREAM_CHAT]).tag("a", [aTag]).limit(100); + rb.withFilter().kinds([LIVE_STREAM_CHAT]).tag("a", [aTag]).limit(limit); return rb; }, [link.id, since, eZaps]); diff --git a/src/index.css b/src/index.css index 11a0690..9e740d9 100644 --- a/src/index.css +++ b/src/index.css @@ -48,6 +48,10 @@ a { display: flex; } +.f-1 { + flex: 1; +} + .f-grow { flex-grow: 1; } @@ -228,6 +232,12 @@ input[type="checkbox"]:checked:after { display: block; } +.plain-paper { + background: #171717; + border-radius: 16px; + padding: 8px 16px; +} + div.paper { background: #171717; border-radius: 16px; diff --git a/src/index.tsx b/src/index.tsx index 924c474..b48c8da 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -25,6 +25,7 @@ import { IntlProvider } from "intl"; import { WidgetsPage } from "pages/widgets"; import { AlertsPage } from "pages/alerts"; import { unixNowMs } from "@snort/shared"; +import { StreamSummaryPage } from "pages/summary"; export enum StreamState { Live = "live", @@ -94,6 +95,10 @@ const router = createBrowserRouter([ path: "/widgets", element: , }, + { + path: "/summary/:id", + element: , + }, { path: "*", element: , diff --git a/src/pages/summary.tsx b/src/pages/summary.tsx new file mode 100644 index 0000000..0f1599b --- /dev/null +++ b/src/pages/summary.tsx @@ -0,0 +1,235 @@ +import { useMemo } from "react"; +import { unixNow } from "@snort/shared"; +import { useLocation } from "react-router-dom"; +import { EventKind, NostrEvent, NostrLink, ParsedZap } from "@snort/system"; +import { useEventReactions } from "@snort/system-react"; +import { FormattedDate, FormattedMessage, FormattedNumber } from "react-intl"; +import { Bar, BarChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts"; + +import { LIVE_STREAM_CHAT } from "const"; +import { Profile } from "element/profile"; +import { StatePill } from "element/state-pill"; +import { useCurrentStreamFeed } from "hooks/current-stream-feed"; +import { useLiveChatFeed } from "hooks/live-chat"; +import { useStreamLink } from "hooks/stream-link"; +import { StreamState } from "index"; +import { formatSats } from "number"; +import { findTag, getEventFromLocationState } from "utils"; + +export function StreamSummaryPage() { + const location = useLocation(); + const evPreload = getEventFromLocationState(location.state); + const link = useStreamLink(); + if (link) { + return ; + } +} + +interface StatSlot { + time: number; + zaps: number; + messages: number; + reactions: number; +} + +export function StreamSummary({ link, preload }: { link: NostrLink; preload?: NostrEvent }) { + const ev = useCurrentStreamFeed(link, true, preload); + const data = useLiveChatFeed(link, undefined, 5_000); + const reactions = useEventReactions(link, data.reactions); + + const chatSummary = useMemo(() => { + return Object.entries( + data.messages.reduce((acc, v) => { + acc[v.pubkey] ??= []; + acc[v.pubkey].push(v); + return acc; + }, {} as Record>) + ) + .map(([k, v]) => ({ + pubkey: k, + messages: v, + })) + .sort((a, b) => (a.messages.length > b.messages.length ? -1 : 1)); + }, [data.messages]); + + const zapsSummary = useMemo(() => { + return Object.entries( + reactions.zaps.reduce((acc, v) => { + if (!v.sender) return acc; + acc[v.sender] ??= []; + acc[v.sender].push(v); + return acc; + }, {} as Record>) + ) + .map(([k, v]) => ({ + pubkey: k, + zaps: v, + total: v.reduce((acc, vv) => acc + vv.amount, 0), + })) + .sort((a, b) => (a.total > b.total ? -1 : 1)); + }, [reactions.zaps]); + + const title = findTag(ev, "title"); + const summary = findTag(ev, "summary"); + const status = findTag(ev, "status"); + const starts = findTag(ev, "starts"); + + const Day = 60 * 60 * 24; + const startTime = starts ? Number(starts) : ev?.created_at ?? unixNow(); + const endTime = status === StreamState.Live ? unixNow() : ev?.created_at ?? unixNow(); + + const streamLength = endTime - startTime; + const windowSize = streamLength > Day ? Day : 60 * 10; + + const stats = useMemo(() => { + let min = unixNow(); + let max = 0; + const ret = [...data.messages, ...data.reactions] + .sort((a, b) => (a.created_at > b.created_at ? -1 : 1)) + .reduce((acc, v) => { + const time = Math.floor(v.created_at - (v.created_at % windowSize)); + if (time < min) { + min = time; + } + if (time > max) { + max = time; + } + const key = time.toString(); + acc[key] ??= { + time, + zaps: 0, + messages: 0, + reactions: 0, + }; + + if (v.kind === LIVE_STREAM_CHAT) { + acc[key].messages++; + } else if (v.kind === EventKind.ZapReceipt) { + acc[key].zaps++; + } else if (v.kind === EventKind.Reaction) { + acc[key].reactions++; + } else { + console.debug("Uncounted stat", v); + } + return acc; + }, {} as Record); + + // fill empty time slots + for (let x = min; x < max; x += windowSize) { + ret[x.toString()] ??= { + time: x, + zaps: 0, + messages: 0, + reactions: 0, + }; + } + return ret; + }, [data]); + + return ( +
+

{title}

+

{summary}

+
+ + {streamLength > 0 && ( + , + }} + /> + )} +
+

+ +

+ + + + + + + + { + if (active && payload && payload.length) { + const data = payload[0].payload as StatSlot; + return ( +
+
+ +
+
+
+ +
+
{data.messages}
+
+
+
+ +
+
{data.reactions}
+
+
+
+ +
+
{data.zaps}
+
+
+ ); + } + return null; + }} + /> +
+
+ +
+
+

+ +

+
+ {chatSummary.slice(0, 5).map(a => ( +
+ +
+ , + }} + /> +
+
+ ))} +
+
+
+

+ +

+
+ {zapsSummary.slice(0, 5).map(a => ( +
+ +
+ +
+
+ ))} +
+
+
+
+ ); +} diff --git a/yarn.lock b/yarn.lock index dbfb57d..ad8ff28 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1361,6 +1361,15 @@ __metadata: languageName: node linkType: hard +"@babel/runtime@npm:^7.1.2": + version: 7.23.2 + resolution: "@babel/runtime@npm:7.23.2" + dependencies: + regenerator-runtime: ^0.14.0 + checksum: 6c4df4839ec75ca10175f636d6362f91df8a3137f86b38f6cd3a4c90668a0fe8e9281d320958f4fbd43b394988958585a17c3aab2a4ea6bf7316b22916a371fb + languageName: node + linkType: hard + "@babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.9.2": version: 7.22.11 resolution: "@babel/runtime@npm:7.22.11" @@ -2752,6 +2761,75 @@ __metadata: languageName: node linkType: hard +"@types/d3-array@npm:^3.0.3": + version: 3.2.1 + resolution: "@types/d3-array@npm:3.2.1" + checksum: 8a41cee0969e53bab3f56cc15c4e6c9d76868d6daecb2b7d8c9ce71e0ececccc5a8239697cc52dadf5c665f287426de5c8ef31a49e7ad0f36e8846889a383df4 + languageName: node + linkType: hard + +"@types/d3-color@npm:*": + version: 3.1.3 + resolution: "@types/d3-color@npm:3.1.3" + checksum: 8a0e79a709929502ec4effcee2c786465b9aec51b653ba0b5d05dbfec3e84f418270dd603002d94021885061ff592f614979193bd7a02ad76317f5608560e357 + languageName: node + linkType: hard + +"@types/d3-ease@npm:^3.0.0": + version: 3.0.2 + resolution: "@types/d3-ease@npm:3.0.2" + checksum: 0885219966294bfc99548f37297e1c75e75da812a5f3ec941977ebb57dcab0a25acec5b2bbd82d09a49d387daafca08521ca269b7e4c27ddca7768189e987b54 + languageName: node + linkType: hard + +"@types/d3-interpolate@npm:^3.0.1": + version: 3.0.4 + resolution: "@types/d3-interpolate@npm:3.0.4" + dependencies: + "@types/d3-color": "*" + checksum: efd2770e174e84fc7316fdafe03cf3688451f767dde1fa6211610137f495be7f3923db7e1723a6961a0e0e9ae0ed969f4f47c038189fa0beb1d556b447922622 + languageName: node + linkType: hard + +"@types/d3-path@npm:*": + version: 3.0.2 + resolution: "@types/d3-path@npm:3.0.2" + checksum: 0107d89510e19e478c168e0e5df0c901f57e12f42f90f961a52b0b1e5b58182dde14a5b27ef66a0a769f09119f305d484dd8dc5adca17f6dd74baab87ad36a98 + languageName: node + linkType: hard + +"@types/d3-scale@npm:^4.0.2": + version: 4.0.8 + resolution: "@types/d3-scale@npm:4.0.8" + dependencies: + "@types/d3-time": "*" + checksum: 3b1906da895564f73bb3d0415033d9a8aefe7c4f516f970176d5b2ff7a417bd27ae98486e9a9aa0472001dc9885a9204279a1973a985553bdb3ee9bbc1b94018 + languageName: node + linkType: hard + +"@types/d3-shape@npm:^3.1.0": + version: 3.1.5 + resolution: "@types/d3-shape@npm:3.1.5" + dependencies: + "@types/d3-path": "*" + checksum: 8476c3908ec70637c8d1e5b103eebd0155fe2b398280c782e318007b444b9abaed65aba35b426f701af14a880cec3f4e47bdbf3a2a45545e0f40fa45e7492708 + languageName: node + linkType: hard + +"@types/d3-time@npm:*, @types/d3-time@npm:^3.0.0": + version: 3.0.3 + resolution: "@types/d3-time@npm:3.0.3" + checksum: a071826c80efdb1999e6406fef2db516d45f3906da3a9a4da8517fa863bae53c4c1056ca5347a20921660607d21ec874fd2febe0e961adb7be6954255587d08f + languageName: node + linkType: hard + +"@types/d3-timer@npm:^3.0.0": + version: 3.0.2 + resolution: "@types/d3-timer@npm:3.0.2" + checksum: 1643eebfa5f4ae3eb00b556bbc509444d88078208ec2589ddd8e4a24f230dd4cf2301e9365947e70b1bee33f63aaefab84cd907822aae812b9bc4871b98ab0e1 + languageName: node + linkType: hard + "@types/eslint-scope@npm:^3.7.3": version: 3.7.4 resolution: "@types/eslint-scope@npm:3.7.4" @@ -4121,6 +4199,13 @@ __metadata: languageName: node linkType: hard +"classnames@npm:^2.2.5": + version: 2.3.2 + resolution: "classnames@npm:2.3.2" + checksum: 2c62199789618d95545c872787137262e741f9db13328e216b093eea91c85ef2bfb152c1f9e63027204e2559a006a92eb74147d46c800a9f96297ae1d9f96f4e + languageName: node + linkType: hard + "clean-css@npm:^5.2.2": version: 5.3.2 resolution: "clean-css@npm:5.3.2" @@ -4592,6 +4677,99 @@ __metadata: languageName: node linkType: hard +"d3-array@npm:2 - 3, d3-array@npm:2.10.0 - 3, d3-array@npm:^3.1.6": + version: 3.2.4 + resolution: "d3-array@npm:3.2.4" + dependencies: + internmap: 1 - 2 + checksum: a5976a6d6205f69208478bb44920dd7ce3e788c9dceb86b304dbe401a4bfb42ecc8b04c20facde486e9adcb488b5d1800d49393a3f81a23902b68158e12cddd0 + languageName: node + linkType: hard + +"d3-color@npm:1 - 3": + version: 3.1.0 + resolution: "d3-color@npm:3.1.0" + checksum: 4931fbfda5d7c4b5cfa283a13c91a954f86e3b69d75ce588d06cde6c3628cebfc3af2069ccf225e982e8987c612aa7948b3932163ce15eb3c11cd7c003f3ee3b + languageName: node + linkType: hard + +"d3-ease@npm:^3.0.1": + version: 3.0.1 + resolution: "d3-ease@npm:3.0.1" + checksum: 06e2ee5326d1e3545eab4e2c0f84046a123dcd3b612e68858219aa034da1160333d9ce3da20a1d3486d98cb5c2a06f7d233eee1bc19ce42d1533458bd85dedcd + languageName: node + linkType: hard + +"d3-format@npm:1 - 3": + version: 3.1.0 + resolution: "d3-format@npm:3.1.0" + checksum: f345ec3b8ad3cab19bff5dead395bd9f5590628eb97a389b1dd89f0b204c7c4fc1d9520f13231c2c7cf14b7c9a8cf10f8ef15bde2befbab41454a569bd706ca2 + languageName: node + linkType: hard + +"d3-interpolate@npm:1.2.0 - 3, d3-interpolate@npm:^3.0.1": + version: 3.0.1 + resolution: "d3-interpolate@npm:3.0.1" + dependencies: + d3-color: 1 - 3 + checksum: a42ba314e295e95e5365eff0f604834e67e4a3b3c7102458781c477bd67e9b24b6bb9d8e41ff5521050a3f2c7c0c4bbbb6e187fd586daa3980943095b267e78b + languageName: node + linkType: hard + +"d3-path@npm:^3.1.0": + version: 3.1.0 + resolution: "d3-path@npm:3.1.0" + checksum: 2306f1bd9191e1eac895ec13e3064f732a85f243d6e627d242a313f9777756838a2215ea11562f0c7630c7c3b16a19ec1fe0948b1c82f3317fac55882f6ee5d8 + languageName: node + linkType: hard + +"d3-scale@npm:^4.0.2": + version: 4.0.2 + resolution: "d3-scale@npm:4.0.2" + dependencies: + d3-array: 2.10.0 - 3 + d3-format: 1 - 3 + d3-interpolate: 1.2.0 - 3 + d3-time: 2.1.1 - 3 + d3-time-format: 2 - 4 + checksum: a9c770d283162c3bd11477c3d9d485d07f8db2071665f1a4ad23eec3e515e2cefbd369059ec677c9ac849877d1a765494e90e92051d4f21111aa56791c98729e + languageName: node + linkType: hard + +"d3-shape@npm:^3.1.0": + version: 3.2.0 + resolution: "d3-shape@npm:3.2.0" + dependencies: + d3-path: ^3.1.0 + checksum: de2af5fc9a93036a7b68581ca0bfc4aca2d5a328aa7ba7064c11aedd44d24f310c20c40157cb654359d4c15c3ef369f95ee53d71221017276e34172c7b719cfa + languageName: node + linkType: hard + +"d3-time-format@npm:2 - 4": + version: 4.1.0 + resolution: "d3-time-format@npm:4.1.0" + dependencies: + d3-time: 1 - 3 + checksum: 7342bce28355378152bbd4db4e275405439cabba082d9cd01946d40581140481c8328456d91740b0fe513c51ec4a467f4471ffa390c7e0e30ea30e9ec98fcdf4 + languageName: node + linkType: hard + +"d3-time@npm:1 - 3, d3-time@npm:2.1.1 - 3, d3-time@npm:^3.0.0": + version: 3.1.0 + resolution: "d3-time@npm:3.1.0" + dependencies: + d3-array: 2 - 3 + checksum: 613b435352a78d9f31b7f68540788186d8c331b63feca60ad21c88e9db1989fe888f97f242322ebd6365e45ec3fb206a4324cd4ca0dfffa1d9b5feb856ba00a7 + languageName: node + linkType: hard + +"d3-timer@npm:^3.0.1": + version: 3.0.1 + resolution: "d3-timer@npm:3.0.1" + checksum: 1cfddf86d7bca22f73f2c427f52dfa35c49f50d64e187eb788dcad6e927625c636aa18ae4edd44d084eb9d1f81d8ca4ec305dae7f733c15846a824575b789d73 + languageName: node + linkType: hard + "debug@npm:2.6.9": version: 2.6.9 resolution: "debug@npm:2.6.9" @@ -4613,6 +4791,13 @@ __metadata: languageName: node linkType: hard +"decimal.js-light@npm:^2.4.1": + version: 2.5.1 + resolution: "decimal.js-light@npm:2.5.1" + checksum: f5a2c7eac1c4541c8ab8a5c8abea64fc1761cefc7794bd5f8afd57a8a78d1b51785e0c4e4f85f4895a043eaa90ddca1edc3981d1263eb6ddce60f32bf5fe66c9 + languageName: node + linkType: hard + "deep-equal@npm:^2.0.5": version: 2.2.2 resolution: "deep-equal@npm:2.2.2" @@ -4803,6 +4988,15 @@ __metadata: languageName: node linkType: hard +"dom-helpers@npm:^3.4.0": + version: 3.4.0 + resolution: "dom-helpers@npm:3.4.0" + dependencies: + "@babel/runtime": ^7.1.2 + checksum: 58d9f1c4a96daf77eddc63ae1236b826e1cddd6db66bbf39b18d7e21896d99365b376593352d52a60969d67fa4a8dbef26adc1439fa2c1b355efa37cacbaf637 + languageName: node + linkType: hard + "dom-serializer@npm:^1.0.1": version: 1.4.1 resolution: "dom-serializer@npm:1.4.1" @@ -5294,7 +5488,7 @@ __metadata: languageName: node linkType: hard -"eventemitter3@npm:^4.0.0": +"eventemitter3@npm:^4.0.0, eventemitter3@npm:^4.0.1": version: 4.0.7 resolution: "eventemitter3@npm:4.0.7" checksum: 1875311c42fcfe9c707b2712c32664a245629b42bb0a5a84439762dd0fd637fc54d078155ea83c2af9e0323c9ac13687e03cfba79b03af9f40c89b4960099374 @@ -5398,6 +5592,13 @@ __metadata: languageName: node linkType: hard +"fast-equals@npm:^5.0.0": + version: 5.0.1 + resolution: "fast-equals@npm:5.0.1" + checksum: fbb3b6a74f3a0fa930afac151ff7d01639159b4fddd2678b5d50708e0ba38e9ec14602222d10dadb8398187342692c04fbef5a62b1cfcc7942fe03e754e064bc + languageName: node + linkType: hard + "fast-glob@npm:^3.2.11, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0": version: 3.3.1 resolution: "fast-glob@npm:3.3.1" @@ -6288,6 +6489,13 @@ __metadata: languageName: node linkType: hard +"internmap@npm:1 - 2": + version: 2.0.3 + resolution: "internmap@npm:2.0.3" + checksum: 7ca41ec6aba8f0072fc32fa8a023450a9f44503e2d8e403583c55714b25efd6390c38a87161ec456bf42d7bc83aab62eb28f5aef34876b1ac4e60693d5e1d241 + languageName: node + linkType: hard + "interpret@npm:^3.1.1": version: 3.1.1 resolution: "interpret@npm:3.1.1" @@ -7068,7 +7276,7 @@ __metadata: languageName: node linkType: hard -"lodash@npm:^4.17.15, lodash@npm:^4.17.20, lodash@npm:^4.17.21": +"lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21": version: 4.17.21 resolution: "lodash@npm:4.17.21" checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 @@ -8378,7 +8586,7 @@ __metadata: languageName: node linkType: hard -"prop-types@npm:^15.7.2, prop-types@npm:^15.8.1": +"prop-types@npm:^15.6.2, prop-types@npm:^15.7.2, prop-types@npm:^15.8.1": version: 15.8.1 resolution: "prop-types@npm:15.8.1" dependencies: @@ -8577,7 +8785,7 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^16.13.1, react-is@npm:^16.7.0": +"react-is@npm:^16.10.2, react-is@npm:^16.13.1, react-is@npm:^16.7.0": version: 16.13.1 resolution: "react-is@npm:16.13.1" checksum: f7a19ac3496de32ca9ae12aa030f00f14a3d45374f1ceca0af707c831b2a6098ef0d6bdae51bd437b0a306d7f01d4677fcc8de7c0d331eb47ad0f46130e53c5f @@ -8598,6 +8806,13 @@ __metadata: languageName: node linkType: hard +"react-lifecycles-compat@npm:^3.0.4": + version: 3.0.4 + resolution: "react-lifecycles-compat@npm:3.0.4" + checksum: a904b0fc0a8eeb15a148c9feb7bc17cec7ef96e71188280061fc340043fd6d8ee3ff233381f0e8f95c1cf926210b2c4a31f38182c8f35ac55057e453d6df204f + languageName: node + linkType: hard + "react-remove-scroll-bar@npm:^2.3.3": version: 2.3.4 resolution: "react-remove-scroll-bar@npm:2.3.4" @@ -8633,6 +8848,18 @@ __metadata: languageName: node linkType: hard +"react-resize-detector@npm:^8.0.4": + version: 8.1.0 + resolution: "react-resize-detector@npm:8.1.0" + dependencies: + lodash: ^4.17.21 + peerDependencies: + react: ^16.0.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 + checksum: 45e6b87ea7331406bed2a806d0cea98c1467d53a7cfcdf19c2dd55a3460047917d3b175d9cceea6f314b65eb54858cbb981acffd007d67aa16388e517dafb83e + languageName: node + linkType: hard + "react-router-dom@npm:^6.13.0": version: 6.15.0 resolution: "react-router-dom@npm:6.15.0" @@ -8666,6 +8893,20 @@ __metadata: languageName: node linkType: hard +"react-smooth@npm:^2.0.4": + version: 2.0.5 + resolution: "react-smooth@npm:2.0.5" + dependencies: + fast-equals: ^5.0.0 + react-transition-group: 2.9.0 + peerDependencies: + prop-types: ^15.6.0 + react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 + react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 + checksum: 914c17f741e8b533ff6e3d5e3285aea0625cdd0f98e04202d01351f9516dbdc0a0e297dc22cc2377d6916fb819da8d4ed999c0314a4c186592ca51870012e6f7 + languageName: node + linkType: hard + "react-style-singleton@npm:^2.2.1": version: 2.2.1 resolution: "react-style-singleton@npm:2.2.1" @@ -8693,6 +8934,21 @@ __metadata: languageName: node linkType: hard +"react-transition-group@npm:2.9.0": + version: 2.9.0 + resolution: "react-transition-group@npm:2.9.0" + dependencies: + dom-helpers: ^3.4.0 + loose-envify: ^1.4.0 + prop-types: ^15.6.2 + react-lifecycles-compat: ^3.0.4 + peerDependencies: + react: ">=15.0.0" + react-dom: ">=15.0.0" + checksum: d8c9e50aabdc2cfc324e5cdb0ad1c6eecb02e1c0cd007b26d5b30ccf49015e900683dd489348c71fba4055858308d9ba7019e0d37d0e8d37bd46ed098788f670 + languageName: node + linkType: hard + "react-transition-state@npm:^2.1.0": version: 2.1.1 resolution: "react-transition-state@npm:2.1.1" @@ -8747,6 +9003,36 @@ __metadata: languageName: node linkType: hard +"recharts-scale@npm:^0.4.4": + version: 0.4.5 + resolution: "recharts-scale@npm:0.4.5" + dependencies: + decimal.js-light: ^2.4.1 + checksum: e970377190a610e684a32c7461c7684ac3603c2e0ac0020bbba1eea9d099b38138143a8e80bf769bb49c0b7cecf22a2f5c6854885efed2d56f4540d4aa7052bd + languageName: node + linkType: hard + +"recharts@npm:^2.9.3": + version: 2.9.3 + resolution: "recharts@npm:2.9.3" + dependencies: + classnames: ^2.2.5 + eventemitter3: ^4.0.1 + lodash: ^4.17.19 + react-is: ^16.10.2 + react-resize-detector: ^8.0.4 + react-smooth: ^2.0.4 + recharts-scale: ^0.4.4 + tiny-invariant: ^1.3.1 + victory-vendor: ^36.6.8 + peerDependencies: + prop-types: ^15.6.0 + react: ^16.0.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 + checksum: e08bcc76a1ec2ea0cbcfcf8f57013acd11fb5ac44f40f43bb208880a8c410a9bc8d0eb421e8d1a5943eb0899729ae136a579a8008c720cb2e18367771edd86d7 + languageName: node + linkType: hard + "rechoir@npm:^0.8.0": version: 0.8.0 resolution: "rechoir@npm:0.8.0" @@ -9548,6 +9834,7 @@ __metadata: react-intl: ^6.4.4 react-router-dom: ^6.13.0 react-tag-input-component: ^2.0.2 + recharts: ^2.9.3 semantic-sdp: ^3.26.3 source-map-loader: ^4.0.1 terser-webpack-plugin: ^5.3.9 @@ -9875,6 +10162,13 @@ __metadata: languageName: node linkType: hard +"tiny-invariant@npm:^1.3.1": + version: 1.3.1 + resolution: "tiny-invariant@npm:1.3.1" + checksum: 872dbd1ff20a21303a2fd20ce3a15602cfa7fcf9b228bd694a52e2938224313b5385a1078cb667ed7375d1612194feaca81c4ecbe93121ca1baebe344de4f84c + languageName: node + linkType: hard + "to-fast-properties@npm:^2.0.0": version: 2.0.0 resolution: "to-fast-properties@npm:2.0.0" @@ -10262,6 +10556,28 @@ __metadata: languageName: node linkType: hard +"victory-vendor@npm:^36.6.8": + version: 36.6.12 + resolution: "victory-vendor@npm:36.6.12" + dependencies: + "@types/d3-array": ^3.0.3 + "@types/d3-ease": ^3.0.0 + "@types/d3-interpolate": ^3.0.1 + "@types/d3-scale": ^4.0.2 + "@types/d3-shape": ^3.1.0 + "@types/d3-time": ^3.0.0 + "@types/d3-timer": ^3.0.0 + d3-array: ^3.1.6 + d3-ease: ^3.0.1 + d3-interpolate: ^3.0.1 + d3-scale: ^4.0.2 + d3-shape: ^3.1.0 + d3-time: ^3.0.0 + d3-timer: ^3.0.1 + checksum: cb7e1b48621129f12c71cf532391c4b8f5065b620557cc8758c30ad17f8453d43c8c0552fff91095e3d7ac40a9ad465d74a9cf3b721b14e4b691201ff6d26390 + languageName: node + linkType: hard + "watchpack@npm:^2.4.0": version: 2.4.0 resolution: "watchpack@npm:2.4.0"