diff --git a/frontend/package.json b/frontend/package.json
index 0a6781b..6564cad 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -9,6 +9,11 @@
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.4.3",
+ "@visx/axis": "^3.1.0",
+ "@visx/curve": "^3.0.0",
+ "@visx/group": "^3.0.0",
+ "@visx/scale": "^3.0.0",
+ "@visx/shape": "^3.0.0",
"axios": "1.2.1",
"date-fns": "2.29.3",
"ejs": "3.1.8",
diff --git a/frontend/src/Call/Activity.js b/frontend/src/Call/Activity.js
new file mode 100644
index 0000000..a000c06
--- /dev/null
+++ b/frontend/src/Call/Activity.js
@@ -0,0 +1,69 @@
+import React, { useEffect, useLayoutEffect, useState, useRef, useCallback, useMemo } from "react";
+import { Link, useLocation, useParams, useNavigate } from 'react-router-dom';
+import FilterModal from "./components/FilterModal";
+import GroupModal from "./components/GroupModal";
+import CalendarModal from "./components/CalendarModal";
+import CallPlayer from "./CallPlayer";
+
+import { useSelector, useDispatch } from 'react-redux'
+import { setFilter, setDateFilter } from "../features/callPlayer/callPlayerSlice";
+
+import { useGetStatsQuery,useGetTalkgroupsQuery } from '../features/api/apiSlice'
+import ActivityChart from "./ActivityChart";
+import { selectSystem } from "../features/systems/systemsSlice";
+import {
+ Container,
+ Label,
+ Rail,
+ Sticky,
+ Menu,
+ Icon,
+ Sidebar,
+ Header
+
+} from "semantic-ui-react";
+import "./CallPlayer.css";
+import queryString from '../query-string';
+import io from 'socket.io-client';
+import { useCallLink } from "./components/CallLinks";
+
+
+function Activity(props) {
+ const { shortName } = useParams();
+ const { data: statsData, isSuccess: isStatsSuccess } = useGetStatsQuery(shortName);
+ const { data: talkgroupData, isSuccess: isTalkgroupsSuccess } = useGetTalkgroupsQuery(shortName);
+
+ const talkgroupStats = useMemo(() => {
+ if (statsData ) {
+ const result =[]
+ for (const tgNum in statsData.talkgroupStats) {
+ let tg = tgNum;
+ if (talkgroupData && talkgroupData.talkgroups[tgNum] !== undefined) {
+ tg = talkgroupData.talkgroups[tgNum].description;
+ }
+ result.push();
+ }
+ return result;
+ } else {
+ return [];
+ }
+
+
+ }, [statsData, talkgroupData]);
+
+
+ return (
+
+
+ {
+ talkgroupStats.map( chart => {
+ return chart
+ })
+ }
+
+
+ )
+
+}
+
+export default Activity;
\ No newline at end of file
diff --git a/frontend/src/Call/ActivityChart.js b/frontend/src/Call/ActivityChart.js
new file mode 100644
index 0000000..508cc01
--- /dev/null
+++ b/frontend/src/Call/ActivityChart.js
@@ -0,0 +1,102 @@
+import React from "react";
+import { Group } from '@visx/group';
+import { curveStep} from '@visx/curve';
+import { LinePath } from '@visx/shape';
+import { scaleLinear, scaleTime } from '@visx/scale';
+import { timeParse, timeFormat } from 'd3-time-format';
+import { AxisBottom, AxisLeft } from '@visx/axis';
+import { Loader } from "semantic-ui-react";
+import {
+ Header
+} from "semantic-ui-react";
+
+function ActivityChart(props) {
+
+ if (!props.data) {
+ return (
+ Loading
+ )
+ }
+
+ var callTotals = [];
+
+
+ const now = new Date();
+ var maxDate = now;
+ var minDate = now;
+ var minValue = 0;
+ var maxValue = 0;
+ var MS_PER_MINUTE = 60000;
+
+ for (let j = 0; j < props.data.length; j++) {
+ let spotsBack = j;//statistic.callTotals.length - j;
+ let time = new Date(now - spotsBack * 15 * MS_PER_MINUTE);
+ if (time < minDate) minDate = time;
+ if (props.data[j] > maxValue)
+ maxValue = props.data[j];
+ callTotals.push({ y: props.data[j], x: time });
+ }
+
+
+
+
+
+
+ // Define the graph dimensions and margins
+ const width = 500; //props.width;
+ const height = 250;
+ const margin = { top: 20, bottom: 40, left: 40, right: 20 };
+ const parseDate = timeParse("%Y%m%d");
+ const format = timeFormat("%b %d");
+ const formatDate = (date) => format(parseDate(date));
+ const parseTime = timeParse('%Y-%m-%dT%H:%M:%S.%LZ');
+
+ // Then we'll create some bounds
+ const xMax = width - margin.left - margin.right;
+ const yMax = height - margin.top - margin.bottom;
+
+ var xScale, yScale;
+
+ // We'll use some mock data from `@vx/mock-data` for this.
+ // scales
+ xScale = scaleTime({
+ range: [0, xMax],
+ domain: [minDate, maxDate],
+ tickFormat: () => (val) => formatDate(val)
+ });
+ yScale = scaleLinear({
+ range: [yMax, 0],
+ domain: [0, maxValue],
+ });
+
+ const handleClick = (event) => {
+ console.log('You clicked on:', event);
+ };
+ // accessors
+ const x = d => xScale(d.x);
+ const y = d => yScale(d.y);
+ return (
+
+
+
+
+ );
+}
+
+export default ActivityChart;
+
+
diff --git a/frontend/src/Call/Calls.js b/frontend/src/Call/Calls.js
index 703386e..02a64a8 100644
--- a/frontend/src/Call/Calls.js
+++ b/frontend/src/Call/Calls.js
@@ -1,19 +1,17 @@
-import React, { useEffect, useLayoutEffect, useState, useRef, useCallback, useMemo } from "react";
+import React, { useEffect, useLayoutEffect, useState, useRef, useMemo } from "react";
import { Link, useLocation, useParams, useNavigate } from 'react-router-dom';
import FilterModal from "./components/FilterModal";
import GroupModal from "./components/GroupModal";
import CalendarModal from "./components/CalendarModal";
import CallPlayer from "./CallPlayer";
+import Activity from "./Activity";
import { useSelector, useDispatch } from 'react-redux'
import { setFilter, setDateFilter } from "../features/callPlayer/callPlayerSlice";
import { getCalls, addCall, getOlderCalls, getNewerCalls } from "../features/calls/callsSlice";
import { useGetGroupsQuery, useGetSystemsQuery, } from '../features/api/apiSlice'
-import { selectSystem } from "../features/systems/systemsSlice";
import {
Container,
Label,
- Rail,
- Sticky,
Menu,
Icon,
Sidebar
@@ -21,7 +19,6 @@ import {
import "./CallPlayer.css";
import queryString from '../query-string';
import io from 'socket.io-client';
-import { useCallLink } from "./components/CallLinks";
@@ -43,6 +40,7 @@ function Calls(props) {
const [filterVisible, setFilterVisible] = useState(false);
const [groupVisible, setGroupVisible] = useState(false);
const [calendarVisible, setCalendarVisible] = useState(false);
+ const [activityVisible, setActivityVisible] = useState(false);
const [isConnected, setIsConnected] = useState(socket.connected);
const [selectCallId, setSelectCallId] = useState(false);
const [live, setLive] = useState(true);
@@ -85,6 +83,7 @@ function Calls(props) {
const handleSidebarToggle = () => setSidebarOpened(!sidebarOpened);
const handleFilterToggle = () => setFilterVisible(!filterVisible);
const handleCalendarToggle = () => setCalendarVisible(!calendarVisible);
+ const handleActivityToggle = () => setActivityVisible(!activityVisible);
const getFilterDescription = () => {
let filter = { type: 'all', code: "", filterStarred: false };
@@ -400,6 +399,10 @@ function Calls(props) {
{system && system.name}
+
+
+ Activity
+
@@ -416,7 +419,10 @@ function Calls(props) {
-
+ {activityVisible
+ ?
+ :
+ }
);
}
diff --git a/frontend/src/features/api/apiSlice.js b/frontend/src/features/api/apiSlice.js
index 8026c3f..c256cae 100644
--- a/frontend/src/features/api/apiSlice.js
+++ b/frontend/src/features/api/apiSlice.js
@@ -44,6 +44,10 @@ export const apiSlice = createApi({
// The URL for the request is '/fakeApi/posts'
query: (shortName) => ({ url: `/${shortName}/talkgroups` })
}),
+ getStats: builder.query({
+ // The URL for the request is '/fakeApi/posts'
+ query: (shortName) => ({ url: `/${shortName}/stats` })
+ }),
addNewEvent: builder.mutation({
query: initialEvent => ({
url: '/events',
@@ -56,4 +60,4 @@ export const apiSlice = createApi({
})
// Export the auto-generated hook for the `getPosts` query endpoint
-export const { useGetGroupsQuery, useGetSystemsQuery, useGetTalkgroupsQuery, useGetEventsQuery, useGetEventQuery, useAddNewEventMutation } = apiSlice
+export const { useGetGroupsQuery, useGetSystemsQuery, useGetTalkgroupsQuery, useGetStatsQuery, useGetEventsQuery, useGetEventQuery, useAddNewEventMutation } = apiSlice
diff --git a/frontend/src/features/callPlayer/callPlayerSlice.js b/frontend/src/features/callPlayer/callPlayerSlice.js
index 7f6a475..245a38f 100644
--- a/frontend/src/features/callPlayer/callPlayerSlice.js
+++ b/frontend/src/features/callPlayer/callPlayerSlice.js
@@ -1,5 +1,5 @@
import { createSlice } from '@reduxjs/toolkit'
-const now = new Date();
+const now = new Date().getTime();
const initialState = {
isWaiting: false,
shortName: "",
diff --git a/frontend/src/features/calls/callsSlice.js b/frontend/src/features/calls/callsSlice.js
index 8fa14c4..22da1d5 100644
--- a/frontend/src/features/calls/callsSlice.js
+++ b/frontend/src/features/calls/callsSlice.js
@@ -54,7 +54,7 @@ export const { selectAll: selectAllCalls, selectById: selectCallById } = callsAd
return selectCallsData(state) ?? initialState
})
*/
-const now = new Date();
+const now = new Date().getTime();
export const callsAdapter = createEntityAdapter({
selectId: (call) => call._id,
@@ -177,7 +177,7 @@ export const getCalls = createAsyncThunk(
'calls/getOlderCalls',
async({},{getState, requestId} ) => {
const {loading,oldestCallTime, newestCallTime} = getState().calls;
- const url = buildCallUrl(getState,"older",oldestCallTime.getTime());
+ const url = buildCallUrl(getState,"older",oldestCallTime);
const res = await fetch(url).then(
(data) => data.json()
)
@@ -188,7 +188,7 @@ export const getCalls = createAsyncThunk(
'calls/getNewerCalls',
async({},{getState, requestId} ) => {
const {loading,oldestCallTime, newestCallTime} = getState().calls;
- const url = buildCallUrl(getState,"newer",newestCallTime.getTime());
+ const url = buildCallUrl(getState,"newer",newestCallTime);
const res = await fetch(url).then(
(data) => data.json()
)
@@ -223,8 +223,8 @@ export const callsSlice = createSlice({
const firstTime = state.data.entities[first].time;
const last = state.data.ids[state.data.ids.length-1];
const lastTime = state.data.entities[last].time;
- state.newestCallTime = new Date(firstTime)
- state.oldestCallTime = new Date(lastTime)
+ state.newestCallTime = new Date(firstTime).getTime();
+ state.oldestCallTime = new Date(lastTime).getTime();
}
},
[getOlderCalls.pending]: (state) => {
@@ -242,8 +242,8 @@ export const callsSlice = createSlice({
const firstTime = state.data.entities[first].time;
const last = state.data.ids[state.data.ids.length-1];
const lastTime = state.data.entities[last].time;
- state.newestCallTime = new Date(firstTime)
- state.oldestCallTime = new Date(lastTime)
+ state.newestCallTime = new Date(firstTime).getTime();
+ state.oldestCallTime = new Date(lastTime).getTime();
}
},
[getNewerCalls.pending]: (state) => {
@@ -261,8 +261,8 @@ export const callsSlice = createSlice({
const firstTime = state.data.entities[first].time;
const last = state.data.ids[state.data.ids.length-1];
const lastTime = state.data.entities[last].time;
- state.newestCallTime = new Date(firstTime)
- state.oldestCallTime = new Date(lastTime)
+ state.newestCallTime = new Date(firstTime).getTime();
+ state.oldestCallTime = new Date(lastTime).getTime();
}
},
[addStar.fulfilled]: (state, {payload}) => {
diff --git a/frontend/yarn.lock b/frontend/yarn.lock
index 165a2e0..e5986fa 100644
--- a/frontend/yarn.lock
+++ b/frontend/yarn.lock
@@ -2674,6 +2674,47 @@
dependencies:
"@types/node" "*"
+"@types/d3-color@*":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.1.0.tgz#6594da178ded6c7c3842f3cc0ac84b156f12f2d4"
+ integrity sha512-HKuicPHJuvPgCD+np6Se9MQvS6OCbJmOjGvylzMJRlDwUXjKTTXs6Pwgk79O09Vj/ho3u1ofXnhFOaEWWPrlwA==
+
+"@types/d3-interpolate@^3.0.1":
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-3.0.1.tgz#e7d17fa4a5830ad56fe22ce3b4fac8541a9572dc"
+ integrity sha512-jx5leotSeac3jr0RePOH1KdR9rISG91QIE4Q2PYTu4OymLTZfA3SrnURSLzKH48HmXVUru50b8nje4E79oQSQw==
+ dependencies:
+ "@types/d3-color" "*"
+
+"@types/d3-path@^1", "@types/d3-path@^1.0.8":
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-1.0.9.tgz#73526b150d14cd96e701597cbf346cfd1fd4a58c"
+ integrity sha512-NaIeSIBiFgSC6IGUBjZWcscUJEq7vpVu7KthHN8eieTV9d9MqkSOZLH4chq1PmcKy06PNe3axLeKmRIyxJ+PZQ==
+
+"@types/d3-scale@^4.0.2":
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.3.tgz#7a5780e934e52b6f63ad9c24b105e33dd58102b5"
+ integrity sha512-PATBiMCpvHJSMtZAMEhc2WyL+hnzarKzI6wAHYjhsonjWJYGq5BXTzQjv4l8m2jO183/4wZ90rKvSeT7o72xNQ==
+ dependencies:
+ "@types/d3-time" "*"
+
+"@types/d3-shape@^1.3.1":
+ version "1.3.8"
+ resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-1.3.8.tgz#c3c15ec7436b4ce24e38de517586850f1fea8e89"
+ integrity sha512-gqfnMz6Fd5H6GOLYixOZP/xlrMtJms9BaS+6oWxTKHNqPGZ93BkWWupQSCYm6YHqx6h9wjRupuJb90bun6ZaYg==
+ dependencies:
+ "@types/d3-path" "^1"
+
+"@types/d3-time@*":
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.0.tgz#e1ac0f3e9e195135361fa1a1d62f795d87e6e819"
+ integrity sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg==
+
+"@types/d3-time@^2.0.0":
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-2.1.1.tgz#743fdc821c81f86537cbfece07093ac39b4bc342"
+ integrity sha512-9MVYlmIgmRR31C5b4FVSWtuMmBHh2mOWQYfl7XAYOa8dsnb7iEmUmRSWSFgXFtkjxO65d7hTUHQC+RhR/9IWFg==
+
"@types/eslint-scope@^3.7.3":
version "3.7.4"
resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16"
@@ -2788,6 +2829,11 @@
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
+"@types/lodash@^4.14.172":
+ version "4.14.192"
+ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.192.tgz#5790406361a2852d332d41635d927f1600811285"
+ integrity sha512-km+Vyn3BYm5ytMO13k9KTp27O75rbQ0NFw+U//g+PX7VZyjCioXaRFisqSIJRECljcTv73G3i6BpglNGHgUQ5A==
+
"@types/mime@*":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10"
@@ -3039,6 +3085,84 @@
"@typescript-eslint/types" "5.47.0"
eslint-visitor-keys "^3.3.0"
+"@visx/axis@^3.1.0":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/@visx/axis/-/axis-3.1.0.tgz#775b221e5abfdec25304c607eeae8cda1a8bade6"
+ integrity sha512-JDj/1VYx0JO0pHFtwoFtYcnqdoZFh/dpHImEl169S5nTslSFlIoNTXA/ekpBP6ELkEZ59gmF1X5k29x6MFBwCA==
+ dependencies:
+ "@types/react" "*"
+ "@visx/group" "3.0.0"
+ "@visx/point" "3.0.1"
+ "@visx/scale" "3.0.0"
+ "@visx/shape" "3.0.0"
+ "@visx/text" "3.0.0"
+ classnames "^2.3.1"
+ prop-types "^15.6.0"
+
+"@visx/curve@3.0.0", "@visx/curve@^3.0.0":
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@visx/curve/-/curve-3.0.0.tgz#c54568472e00a38483c58cf52e4a6ddb2887c2d4"
+ integrity sha512-kvHJDLBeczTQ87ZExSTfRxej06l6o6UiQ0NHf9+xpAin06y6Qk1ThOHHWJTGM6KGzwlu7jEauJGHwZs6nMhDvA==
+ dependencies:
+ "@types/d3-shape" "^1.3.1"
+ d3-shape "^1.0.6"
+
+"@visx/group@3.0.0", "@visx/group@^3.0.0":
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@visx/group/-/group-3.0.0.tgz#e7f9752599bcc7e141ff5317a2a9a502577ab8df"
+ integrity sha512-SFjXhTMcsaVAb1/TVL1KM5vn8gQTIVgSx0ATdDl4BJSFp2ym1lO8LY4jpV4SFweaHnWxVwrrfGLTn5QsYnvmjQ==
+ dependencies:
+ "@types/react" "*"
+ classnames "^2.3.1"
+ prop-types "^15.6.2"
+
+"@visx/point@3.0.1":
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@visx/point/-/point-3.0.1.tgz#77587ddaabf6f3023f09f8a0ce33a2c27c9d64c8"
+ integrity sha512-S5WOBMgEP2xHcgs3A2BFB2vwzrk0tMmn3PGZAbQJ+lu4HlnalDP72klUnxLTH8xclNNvpUHtHM5eLIJXyHx6Pw==
+
+"@visx/scale@3.0.0", "@visx/scale@^3.0.0":
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@visx/scale/-/scale-3.0.0.tgz#727123f0c930d3346a4473e926831c45997e0312"
+ integrity sha512-WSf+wrxZEvu5TPGfGTafzzX1MbogbIxfD9ZKM9p7xfw65v23G0dNMy4bqVBUbOJigONoQkIZyqQ+gz5AJ/ioIg==
+ dependencies:
+ "@types/d3-interpolate" "^3.0.1"
+ "@types/d3-scale" "^4.0.2"
+ "@types/d3-time" "^2.0.0"
+ d3-interpolate "^3.0.1"
+ d3-scale "^4.0.2"
+ d3-time "^2.1.1"
+
+"@visx/shape@3.0.0", "@visx/shape@^3.0.0":
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@visx/shape/-/shape-3.0.0.tgz#a1d4bd0e12cc94c164252f175997932a09c24652"
+ integrity sha512-t6lpP9bIA1vwChDwiOUWl92ro29XF/M8IVNWRA0pm4LGxGGTACvxG3Agfcdi3JprahUVqPpnRCwuR36PDanq3Q==
+ dependencies:
+ "@types/d3-path" "^1.0.8"
+ "@types/d3-shape" "^1.3.1"
+ "@types/lodash" "^4.14.172"
+ "@types/react" "*"
+ "@visx/curve" "3.0.0"
+ "@visx/group" "3.0.0"
+ "@visx/scale" "3.0.0"
+ classnames "^2.3.1"
+ d3-path "^1.0.5"
+ d3-shape "^1.2.0"
+ lodash "^4.17.21"
+ prop-types "^15.5.10"
+
+"@visx/text@3.0.0":
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@visx/text/-/text-3.0.0.tgz#9099c3605027b9ab4c54bde97518a648136c3629"
+ integrity sha512-LW6v5T/gpd9RGw83/ScXncYc6IlcfzXTpaN8WbbxLRI65gdvSqrykwAMR0cbpQmzoVFuZXljqOf0QslHGnBg1w==
+ dependencies:
+ "@types/lodash" "^4.14.172"
+ "@types/react" "*"
+ classnames "^2.3.1"
+ lodash "^4.17.21"
+ prop-types "^15.7.2"
+ reduce-css-calc "^1.3.0"
+
"@webassemblyjs/ast@1.11.1":
version "1.11.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7"
@@ -3630,6 +3754,11 @@ babel-preset-react-app@^10.0.1:
babel-plugin-macros "^3.1.0"
babel-plugin-transform-react-remove-prop-types "^0.4.24"
+balanced-match@^0.4.2:
+ version "0.4.2"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
+ integrity sha512-STw03mQKnGUYtoNjmowo4F2cRmIIxYEGiMsjjwla/u5P1lxadj/05WkNaFjNiKTgJkj8KiXbgAiRTmcQRwQNtg==
+
balanced-match@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
@@ -3913,7 +4042,7 @@ cjs-module-lexer@^1.0.0:
resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40"
integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==
-classnames@^2.2.6:
+classnames@^2.2.6, classnames@^2.3.1:
version "2.3.2"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924"
integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==
@@ -4344,6 +4473,81 @@ csstype@^3.0.2:
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9"
integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==
+d3-array@2:
+ version "2.12.1"
+ resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-2.12.1.tgz#e20b41aafcdffdf5d50928004ececf815a465e81"
+ integrity sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==
+ dependencies:
+ internmap "^1.0.0"
+
+"d3-array@2 - 3", "d3-array@2.10.0 - 3":
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.3.tgz#39f1f4954e4a09ff69ac597c2d61906b04e84740"
+ integrity sha512-JRHwbQQ84XuAESWhvIPaUV4/1UYTBOLiOPGWqgFDHZS1D5QN9c57FbH3QpEnQMYiOXNzKUQyGTZf+EVO7RT5TQ==
+ dependencies:
+ internmap "1 - 2"
+
+"d3-color@1 - 3":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2"
+ integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==
+
+"d3-format@1 - 3":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641"
+ integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==
+
+"d3-interpolate@1.2.0 - 3", d3-interpolate@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d"
+ integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==
+ dependencies:
+ d3-color "1 - 3"
+
+d3-path@1, d3-path@^1.0.5:
+ 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@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396"
+ integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==
+ 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"
+
+d3-shape@^1.0.6, 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 - 4":
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a"
+ integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==
+ dependencies:
+ d3-time "1 - 3"
+
+"d3-time@1 - 3", "d3-time@2.1.1 - 3":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.1.0.tgz#9310db56e992e3c0175e1ef385e545e48a9bb5c7"
+ integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==
+ dependencies:
+ d3-array "2 - 3"
+
+d3-time@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-2.1.1.tgz#e9d8a8a88691f4548e68ca085e5ff956724a6682"
+ integrity sha512-/eIQe/eR4kCQwq7yxi7z4c6qEXf2IYGcjoWB5OOQy4Tq9Uv39/947qlDcN2TLkiTzQWzvnsuYPB9TrWaNfipKQ==
+ dependencies:
+ d3-array "2"
+
damerau-levenshtein@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7"
@@ -5911,6 +6115,16 @@ internal-slot@^1.0.3:
has "^1.0.3"
side-channel "^1.0.4"
+"internmap@1 - 2":
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009"
+ integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==
+
+internmap@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/internmap/-/internmap-1.0.1.tgz#0017cc8a3b99605f0302f2b198d272e015e5df95"
+ integrity sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==
+
ip@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da"
@@ -7072,6 +7286,11 @@ makeerror@1.0.12:
dependencies:
tmpl "1.0.5"
+math-expression-evaluator@^1.2.14:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.4.0.tgz#3d66031117fbb7b9715ea6c9c68c2cd2eebd37e2"
+ integrity sha512-4vRUvPyxdO8cWULGTh9dZWL2tZK6LDBvj+OGHBER7poH9Qdt7kXEoj20wiz4lQUbUXQZFjPbe5mVDo9nutizCw==
+
mdn-data@2.0.14:
version "2.0.14"
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50"
@@ -8288,7 +8507,7 @@ prompts@^2.0.1, prompts@^2.4.2:
kleur "^3.0.3"
sisteransi "^1.0.5"
-prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
+prop-types@^15.5.10, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
@@ -8638,6 +8857,22 @@ redent@^3.0.0:
indent-string "^4.0.0"
strip-indent "^3.0.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 sha512-0dVfwYVOlf/LBA2ec4OwQ6p3X9mYxn/wOl2xTcLwjnPYrkgEfPx3VI4eGCH3rQLlPISG5v9I9bkZosKsNRTRKA==
+ 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"
+
redux-thunk@2.4.2, redux-thunk@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.4.2.tgz#b9d05d11994b99f7a91ea223e8b04cf0afa5ef3b"