feat: stream summary init

This commit is contained in:
Kieran 2023-11-15 10:35:27 +00:00
parent 080955532c
commit ee2cd4bb4d
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
6 changed files with 573 additions and 6 deletions

View File

@ -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",

View File

@ -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<string>) {
export function useLiveChatFeed(link: NostrLink, eZaps?: Array<string>, 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<string>) {
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]);

View File

@ -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;

View File

@ -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: <WidgetsPage />,
},
{
path: "/summary/:id",
element: <StreamSummaryPage />,
},
{
path: "*",
element: <CatchAllRoutePage />,

235
src/pages/summary.tsx Normal file
View File

@ -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 <StreamSummary link={link} preload={evPreload} />;
}
}
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<string, Array<NostrEvent>>)
)
.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<string, Array<ParsedZap>>)
)
.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<string, StatSlot>);
// 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 (
<div className="stream-summary">
<h1>{title}</h1>
<p>{summary}</p>
<div className="flex g8">
<StatePill state={status as StreamState} />
{streamLength > 0 && (
<FormattedMessage
defaultMessage="Stream Duration {duration} mins"
values={{
duration: <FormattedNumber value={streamLength / 60} maximumFractionDigits={2} />,
}}
/>
)}
</div>
<h2>
<FormattedMessage defaultMessage="Summary" />
</h2>
<ResponsiveContainer height={200}>
<BarChart data={Object.values(stats)} margin={{ left: 0, right: 0 }} style={{ userSelect: "none" }}>
<XAxis tick={false} />
<YAxis />
<Bar dataKey="messages" fill="green" stackId="" />
<Bar dataKey="zaps" fill="yellow" stackId="" />
<Bar dataKey="reactions" fill="red" stackId="" />
<Tooltip
cursor={{ fill: "rgba(255,255,255,0.2)" }}
content={({ active, payload }) => {
if (active && payload && payload.length) {
const data = payload[0].payload as StatSlot;
return (
<div className="plain-paper flex f-col g8">
<div>
<FormattedDate value={data.time * 1000} timeStyle="short" dateStyle="short" />
</div>
<div className="flex f-space">
<div>
<FormattedMessage defaultMessage="Messages" />
</div>
<div>{data.messages}</div>
</div>
<div className="flex f-space">
<div>
<FormattedMessage defaultMessage="Reactions" />
</div>
<div>{data.reactions}</div>
</div>
<div className="flex f-space">
<div>
<FormattedMessage defaultMessage="Zaps" />
</div>
<div>{data.zaps}</div>
</div>
</div>
);
}
return null;
}}
/>
</BarChart>
</ResponsiveContainer>
<div className="flex g8">
<div className="plain-paper f-1">
<h3>
<FormattedMessage defaultMessage="Top Chatters" />
</h3>
<div className="flex f-col g8">
{chatSummary.slice(0, 5).map(a => (
<div className="flex f-space f-center" key={a.pubkey}>
<Profile pubkey={a.pubkey} />
<div>
<FormattedMessage
defaultMessage="{n} messages"
values={{
n: <FormattedNumber value={a.messages.length} />,
}}
/>
</div>
</div>
))}
</div>
</div>
<div className="plain-paper f-1">
<h3>
<FormattedMessage defaultMessage="Top Zappers" />
</h3>
<div className="flex f-col g8">
{zapsSummary.slice(0, 5).map(a => (
<div className="flex f-space f-center" key={a.pubkey}>
<Profile pubkey={a.pubkey} />
<div>
<FormattedMessage
defaultMessage="{n} sats"
values={{
n: formatSats(a.total),
}}
/>
</div>
</div>
))}
</div>
</div>
</div>
</div>
);
}

324
yarn.lock
View File

@ -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"