From 018b2088354dda08ce46d40b989950af3ba2578f Mon Sep 17 00:00:00 2001 From: marcobaobao Date: Fri, 6 May 2022 00:49:23 +0200 Subject: [PATCH] MUI update --- .vscode/launch.json | 19 + Dockerfile | 2 +- README.md | 11 +- downloads/.DS_Store | Bin 0 -> 6148 bytes frontend/index.html | 4 - frontend/src/App.tsx | 578 +++----- frontend/src/Home.tsx | 194 +++ frontend/src/Settings.tsx | 158 +++ frontend/src/classes.ts | 31 +- frontend/src/components/StackableResult.tsx | 77 +- .../src/features/settings/settingsSlice.ts | 50 + frontend/src/features/status/statusSlice.ts | 30 + frontend/src/stores/store.ts | 15 + frontend/src/utils.ts | 5 +- package.json | 22 +- pnpm-lock.yaml | 1187 ++++++++++++++--- server/src/core/downloader.ts | 14 +- server/src/main.ts | 9 +- 18 files changed, 1726 insertions(+), 680 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 downloads/.DS_Store create mode 100644 frontend/src/Home.tsx create mode 100644 frontend/src/Settings.tsx create mode 100644 frontend/src/features/settings/settingsSlice.ts create mode 100644 frontend/src/features/status/statusSlice.ts create mode 100644 frontend/src/stores/store.ts diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..9d415a2 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,19 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "chrome", + "request": "launch", + "name": "Launch Chrome against localhost", + "url": "http://localhost:1234", + "webRoot": "${workspaceFolder}", + "breakOnLoad": true, + "sourceMapPathOverrides": { + "/__parcel_source_root/*": "${webRoot}/*" + } + } + ] +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index b1a9d63..32a44ec 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ RUN chmod +x ./fetch-yt-dlp.sh RUN npm install RUN npm run build-all # cleanup -RUN npm remove parcel react react-dom react-bootstrap react-bootstrap-icons +RUN npm remove parcel RUN rm -rf .parcel-cache # expose and run EXPOSE 3022 diff --git a/README.md b/README.md index 0777b3a..2e55706 100644 --- a/README.md +++ b/README.md @@ -20,12 +20,12 @@ Changelog: Refactoring and JSDoc. 04/01/22: Background jobs now are retrieved!! It's still rudimentary but it leverages on yt-dlp resume feature + +05/05/22: Material UI update ``` - -## Now with dark mode - + ## Settings @@ -35,6 +35,9 @@ The avaible settings are currently only: - Extract audio - Switch language + + + Future releases will have: - ~~Multi download~~ *done* - ~~Exctract audio~~ *done* @@ -83,6 +86,8 @@ node dist/main.js - Originally it was 1.8GB circa, now it has been slimmed to ~340MB compressed. This is due to the fact that it encapsule a basic Alpine linux image + FFmpeg + Node.js + Python3 + yt-dlp. - **Am I forced to run it on port 3022?** - Well, yes (until now). +- **Why is it so slow to start a download** + - I genuinely don't know. I know that yt-dlp is slow starting up even on my M1 Mac, so.... ## Todo list - ~~retrieve background tasks~~ diff --git a/downloads/.DS_Store b/downloads/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..2052f370eeead4c2803748ab9d55294324ec0fbc GIT binary patch literal 6148 zcmeHKK}%af5dOC2km@Cuf(H-VgSR44DzpdTDG5~2Qm_Z13O3qOF%pr87CgKkke|_m z2Z>NpYNSdHXyTzzV-JPu%^%R-dJy!R-4%>6hj;W|;{^t3A2VwqAK&{4y?b^T z-~Rh+0=js*Unu^`j~skw?{49=yn-J2{T?{!hK{#ax=P38@ym>O2ggg|6(gRbpMDA- zp|{p{5?>ziY7`l^%wmQ*&6xM-!&5w?x6FT%!u)VLGo4CjQmjoDwn1voxe7X%30HSf3orUzc$HVc?LWKEyaL}B*qd$EXnPyb;ZeE ttEp2|5s3>eniLwh9UDis;!dg&_Gxj5fy2-uTPXfRz|i20XW&*DxB$adP_F<0 literal 0 HcmV?d00001 diff --git a/frontend/index.html b/frontend/index.html index 5b24c82..92a8662 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -5,12 +5,8 @@ - - - yt-dlp Web UI diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index e3506bc..b724114 100755 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,407 +1,195 @@ -import { io } from "socket.io-client"; -import React, { useState, useEffect, useRef, Fragment } from "react"; +import React, { useEffect } from "react" +import { ThemeProvider } from "@emotion/react"; +import { Badge, Box, Container, createTheme, CssBaseline, Divider, IconButton, List, ListItemIcon, ListItemText, Snackbar, styled, Toolbar, Typography } from "@mui/material" +import MuiDrawer from '@mui/material/Drawer'; +import MuiAppBar, { AppBarProps as MuiAppBarProps } from '@mui/material/AppBar'; +import { ChevronLeft, Dashboard, Menu, Settings as SettingsIcon } from "@mui/icons-material"; +import ListItemButton from '@mui/material/ListItemButton'; import { - Container, - Row, - Col, - InputGroup, - FormControl, - Button, - ButtonGroup, -} from "react-bootstrap"; -import { StopFill, GearFill, Translate } from "react-bootstrap-icons"; -import { buildMessage, updateInStateMap, validateDomain, validateIP } from "./utils"; -import { IDLInfo, IDLInfoBase, IMessage } from "./interfaces"; -import { MessageToast } from "./components/MessageToast"; -import { StackableResult } from "./components/StackableResult"; -import { CliArguments } from "./classes"; -import { I18nBuilder } from "./i18n"; -import './App.css'; -import { Footer } from "./components/Footer"; + BrowserRouter as Router, + Route, + Routes, + Link, +} from 'react-router-dom'; +import Home from "./Home"; +import Settings from "./Settings"; +import { io } from "socket.io-client"; +import { RootState, store } from './stores/store'; +import { Provider, useDispatch, useSelector } from "react-redux"; +import { connected } from "./features/status/statusSlice"; + +const theme = createTheme(); + +const drawerWidth: number = 240; const socket = io(`http://${localStorage.getItem('server-addr') || 'localhost'}:3022`) -export function App() { +interface AppBarProps extends MuiAppBarProps { + open?: boolean; +} - const [progressMap, setProgressMap] = useState(new Map()); - const [messageMap, setMessageMap] = useState(new Map()); - const [downloadInfoMap, setDownloadInfoMap] = useState(new Map()); +const AppBar = styled(MuiAppBar, { + shouldForwardProp: (prop) => prop !== 'open', +})(({ theme, open }) => ({ + zIndex: theme.zIndex.drawer + 1, + transition: theme.transitions.create(['width', 'margin'], { + easing: theme.transitions.easing.sharp, + duration: theme.transitions.duration.leavingScreen, + }), + ...(open && { + marginLeft: drawerWidth, + width: `calc(100% - ${drawerWidth}px)`, + transition: theme.transitions.create(['width', 'margin'], { + easing: theme.transitions.easing.sharp, + duration: theme.transitions.duration.enteringScreen, + }), + }), +})); - const [halt, setHalt] = useState(false); - const [url, setUrl] = useState(''); - const [showToast, setShowToast] = useState(false); - const [invalidIP, setInvalidIP] = useState(false); - const [connected, setConnected] = useState(false); - const [updatedBin, setUpdatedBin] = useState(false); - const [showSettings, setShowSettings] = useState(false); - const [showLanguages, setShowLanguages] = useState(false); - const [freeDiskSpace, setFreeDiskSpace] = useState(''); +const Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => prop !== 'open' })( + ({ theme, open }) => ({ + '& .MuiDrawer-paper': { + position: 'relative', + whiteSpace: 'nowrap', + width: drawerWidth, + transition: theme.transitions.create('width', { + easing: theme.transitions.easing.sharp, + duration: theme.transitions.duration.enteringScreen, + }), + boxSizing: 'border-box', + ...(!open && { + overflowX: 'hidden', + transition: theme.transitions.create('width', { + easing: theme.transitions.easing.sharp, + duration: theme.transitions.duration.leavingScreen, + }), + width: theme.spacing(7), + [theme.breakpoints.up('sm')]: { + width: theme.spacing(9), + }, + }), + }, + }), +); - const [darkMode, setDarkMode] = useState(localStorage.getItem('theme') === 'dark'); - const [language, setLanguage] = useState(localStorage.getItem('language') || 'english'); +function AppContent() { + const [open, setOpen] = React.useState(false); + const toggleDrawer = () => { + setOpen(!open); + }; - const xaInput = useRef(null); - const mtInput = useRef(null); - - /* -------------------- Init ----------------------- */ - - const cliArgs = new CliArguments(); - - if (!localStorage.getItem('cliArgs')) { - localStorage.setItem('cliArgs', '') - } - - cliArgs.fromString(localStorage.getItem('cliArgs')) - - const i18n = new I18nBuilder(language); - - /* -------------------- Effects -------------------- */ - - /* WebSocket connect event handler*/ - useEffect(() => { - socket.on('connect', () => { - setConnected(true) - setShowToast(true) - socket.emit('fetch-jobs') - socket.emit('disk-space') - }) - return () => { - socket.disconnect() - } - }, []) - - /* Ask server for pending jobs / background jobs */ - useEffect(() => { - socket.on('pending-jobs', () => { - socket.emit('retrieve-jobs') - }) - }, []) - - /* Handle download information sent by server */ - useEffect(() => { - socket.on('info', (data: IDLInfo) => { - updateInStateMap(data.pid, data.info, downloadInfoMap, setDownloadInfoMap); - }) - }, []) - - /* Handle per-download progress */ - useEffect(() => { - socket.on('progress', (data: IMessage) => { - if (data.status === 'Done!' || data.status === 'Aborted') { - setHalt(false); - updateInStateMap(data.pid, 'Done!', messageMap, setMessageMap); - updateInStateMap(data.pid, 0, progressMap, setProgressMap); - socket.emit('disk-space') - return; - } - updateInStateMap(data.pid, buildMessage(data), messageMap, setMessageMap); - if (data.progress) { - updateInStateMap(data.pid, Math.ceil(Number(data.progress.replace('%', ''))), progressMap, setProgressMap) - } - }) - }, []) - - /* Handle yt-dlp update success */ - useEffect(() => { - socket.on('updated', () => { - setUpdatedBin(true) - setHalt(false) - }) - }, []) - - /* Theme changer */ - useEffect(() => { - darkMode ? - document.body.classList.add('dark') : - document.body.classList.remove('dark'); - }, [darkMode]) - - /* Get disk free space */ - useEffect(() => { - socket.on('free-space', (res: string) => { - setFreeDiskSpace(res) - }) - }, []) - - /* Change language */ - useEffect(() => { - i18n.setLanguage(language) - }, [language]) - - /* -------------------- component functions -------------------- */ - - /** - * Retrive url from input, cli-arguments from checkboxes and emits via WebSocket - */ - const sendUrl = () => { - setHalt(true) - socket.emit('send-url', { - url: url, - params: cliArgs.toString(), - }) - setUrl('') - const input = document.getElementById('urlInput') as HTMLInputElement; - input.value = ''; - } - - /** - * Update the url state whenever the input value changes - * @param e Input change event - */ - const handleUrlChange = (e: React.ChangeEvent) => { - setUrl(e.target.value) - } - - /** - * Update the server ip address state and localstorage whenever the input value changes. - * Validate the ip-addr then set. - * @param e Input change event - */ - const handleAddrChange = (e: React.ChangeEvent) => { - const input = e.target.value; - if (validateIP(input)) { - setInvalidIP(false) - localStorage.setItem('server-addr', input) - } else if (validateDomain(input)) { - setInvalidIP(false) - localStorage.setItem('server-addr', input) - } else { - setInvalidIP(true) - } - } - - /** - * Abort a specific download if id's provided, other wise abort all running ones. - * @param id The download id / pid - * @returns void - */ - const abort = (id?: number) => { - if (id) { - updateInStateMap(id, null, downloadInfoMap, setDownloadInfoMap, true) - socket.emit('abort', { pid: id }) - return - } - socket.emit('abort-all') - setHalt(false) - } - - /** - * Send via WebSocket a message in order to update the yt-dlp binary from server - */ - const updateBinary = () => { - setHalt(true) - socket.emit('update-bin') - } - - /** - * Theme toggler handler - */ - const toggleTheme = () => { - if (darkMode) { - localStorage.setItem('theme', 'light') - setDarkMode(false) - } else { - localStorage.setItem('theme', 'dark') - setDarkMode(true) - } - } - - /** - * Handle extract audio checkbox - */ - const setExtractAudio = () => { - if (cliArgs.extractAudio) { - xaInput.current.checked = false; - cliArgs.extractAudio = false; - - const lStorageItem = localStorage.getItem('cliArgs'); - localStorage.setItem('cliArgs', lStorageItem.replace('-x ', '')); - } else { - xaInput.current.checked = true; - cliArgs.extractAudio = true; - - const lStorageItem = localStorage.getItem('cliArgs'); - localStorage.setItem('cliArgs', lStorageItem.concat('-x ', '')); - } - } - - /** - * Handle no modified time header checkbox - */ - const setNoMTime = () => { - if (cliArgs.noMTime) { - mtInput.current.checked = false; - cliArgs.noMTime = false; - - const lStorageItem = localStorage.getItem('cliArgs'); - localStorage.setItem('cliArgs', lStorageItem.replace('--no-mtime ', '')); - } else { - mtInput.current.checked = true; - cliArgs.noMTime = true; - - const lStorageItem = localStorage.getItem('cliArgs'); - localStorage.setItem('cliArgs', lStorageItem.concat('--no-mtime ', '')); - } - } - - /** - * Language toggler handler - */ - const handleLanguageChage = (event: React.ChangeEvent) => { - setLanguage(event.target.value); - setShowLanguages(false); - localStorage.setItem('language', event.target.value); - } + const status = useSelector((state: RootState) => state.status) + const dispatch = useDispatch() return ( -
- - - -
-

yt-dlp WebUI

-
+ + + + + + + + + + + yt-dlp WebUI + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + theme.palette.mode === 'light' + ? theme.palette.grey[100] + : theme.palette.grey[900], + flexGrow: 1, + height: '100vh', + overflow: 'auto', + }} + > + + + }> + }> + + + + + + ); +} -
- - - - { - !Array.from(messageMap).length ? -
- - -
{i18n.t('statusTitle')}
-
{i18n.t('statusReady')}
- -
-
: null - } - { /*Super big brain flatMap moment*/ - Array.from(messageMap).flatMap(message => ( - - { - /* - Message[0] => key, the pid which is shared with the progress and download Maps - Message[1] => value, the actual formatted message sent from server - */ - } - {message[0] && message[1] && message[1] !== 'Done!' ? - - - - - - - - : null - } - - )) - } - - - - -
- -
- setShowSettings(!showSettings)}> - - - {' '} - setShowLanguages(!showLanguages)}> - - - {showLanguages ? - - : null - } -
- - - {showSettings ? -
-
{i18n.t('serverAddressTitle')}
- - ws:// - - :3022 - -
- - -
- - -
-
- {' '} - -
: - null - } - -
-
- - {i18n.t('bgReminder')} - -
- - - - <> - {i18n.t('toastConnected')}{localStorage.getItem('server-addr') || 'localhost'} - - - - {i18n.t('toastUpdated')} - - - - -
-
- ) +export function App() { + return ( + + + + ); } \ No newline at end of file diff --git a/frontend/src/Home.tsx b/frontend/src/Home.tsx new file mode 100644 index 0000000..3237c19 --- /dev/null +++ b/frontend/src/Home.tsx @@ -0,0 +1,194 @@ +import { Backdrop, Button, CircularProgress, Container, Grid, Paper, Snackbar, TextField, } from "@mui/material"; +import React, { Fragment, useEffect, useState } from "react"; +import { useDispatch, useSelector } from "react-redux"; +import { Socket } from "socket.io-client"; +import { StackableResult } from "./components/StackableResult"; +import { connected, disconnected, downloading, finished } from "./features/status/statusSlice"; +import { IDLInfo, IDLInfoBase, IMessage } from "./interfaces"; +import { RootState } from "./stores/store"; +import { updateInStateMap, } from "./utils"; + +type Props = { + socket: Socket +} + +export default function Home({ socket }: Props) { + // redux state + const settings = useSelector((state: RootState) => state.settings) + const status = useSelector((state: RootState) => state.status) + const dispatch = useDispatch() + + // ephemeral state + const [progressMap, setProgressMap] = useState(new Map()); + const [messageMap, setMessageMap] = useState(new Map()); + const [downloadInfoMap, setDownloadInfoMap] = useState(new Map()); + + const [url, setUrl] = useState(''); + const [showBackdrop, setShowBackdrop] = useState(false); + + /* -------------------- Effects -------------------- */ + /* WebSocket connect event handler*/ + useEffect(() => { + socket.on('connect', () => { + dispatch(connected()); + socket.emit('fetch-jobs') + socket.emit('disk-space') + socket.emit('retrieve-jobs'); + }) + return () => { + socket.disconnect() + } + }, []) + + + /* Ask server for pending jobs / background jobs */ + useEffect(() => { + socket.on('pending-jobs', (count: number) => { + count === 0 ? setShowBackdrop(false) : setShowBackdrop(true) + }) + }, []) + + /* Handle download information sent by server */ + useEffect(() => { + socket.on('info', (data: IDLInfo) => { + setShowBackdrop(false) + dispatch(downloading()) + updateInStateMap(data.pid, data.info, downloadInfoMap, setDownloadInfoMap); + }) + }, []) + + /* Handle per-download progress */ + useEffect(() => { + socket.on('progress', (data: IMessage) => { + if (showBackdrop) { + setShowBackdrop(false) + } + if (!status.downloading) { + dispatch(downloading()) + } + if (data.status === 'Done!' || data.status === 'Aborted') { + updateInStateMap(data.pid, 'Done!', messageMap, setMessageMap); + updateInStateMap(data.pid, 0, progressMap, setProgressMap); + socket.emit('disk-space') + dispatch(finished()) + return; + } + updateInStateMap(data.pid, data, messageMap, setMessageMap); + if (data.progress) { + updateInStateMap(data.pid, Math.ceil(Number(data.progress.replace('%', ''))), progressMap, setProgressMap) + } + }) + }, []) + + /* -------------------- component functions -------------------- */ + + /** + * Retrive url from input, cli-arguments from checkboxes and emits via WebSocket + */ + const sendUrl = () => { + socket.emit('send-url', { + url: url, + params: settings.cliArgs.toString(), + }) + setUrl('') + setTimeout(() => { + const input = document.getElementById('urlInput') as HTMLInputElement; + input.value = ''; + setShowBackdrop(true) + }, 250); + } + + /** + * Update the url state whenever the input value changes + * @param e Input change event + */ + const handleUrlChange = (e: React.ChangeEvent) => { + setUrl(e.target.value) + } + + /** + * Abort a specific download if id's provided, other wise abort all running ones. + * @param id The download id / pid + * @returns void + */ + const abort = (id?: number) => { + if (id) { + updateInStateMap(id, null, downloadInfoMap, setDownloadInfoMap, true) + socket.emit('abort', { pid: id }) + return + } + socket.emit('abort-all') + } + + return ( + + theme.zIndex.drawer + 1 }} + open={showBackdrop} + > + + + + + + + + + + + + + + + + + + + + { /*Super big brain flatMap moment*/ + Array + .from(messageMap) + .filter(flattened => [...flattened][0]) + .filter(flattened => [...flattened][1].toString() !== 'Done!') + .flatMap(message => ( + + { + /* + Message[0] => key, the pid which is shared with the progress and download Maps + Message[1] => value, the actual formatted message sent from server + */ + } + + abort(message[0])} + /> + + + )) + } + + dispatch(disconnected())} + /> + + ); +} \ No newline at end of file diff --git a/frontend/src/Settings.tsx b/frontend/src/Settings.tsx new file mode 100644 index 0000000..f9bcc78 --- /dev/null +++ b/frontend/src/Settings.tsx @@ -0,0 +1,158 @@ +import { Box, Button, Container, FormControl, FormControlLabel, FormGroup, Grid, InputAdornment, InputLabel, MenuItem, Paper, Select, SelectChangeEvent, Snackbar, Stack, Switch, TextField, Toolbar, Typography } from "@mui/material"; +import React, { useEffect, useState } from "react"; +import { useDispatch, useSelector } from "react-redux"; +import { Socket } from "socket.io-client"; +import { LanguageUnion, setCliArgs, setLanguage, setServerAddr } from "./features/settings/settingsSlice"; +import { alreadyUpdated, updated } from "./features/status/statusSlice"; +import { RootState } from "./stores/store"; +import { validateDomain, validateIP } from "./utils"; + +type Props = { + socket: Socket +} + +export default function Settings({ socket }: Props) { + const settings = useSelector((state: RootState) => state.settings) + const status = useSelector((state: RootState) => state.status) + const dispatch = useDispatch() + + const [halt, setHalt] = useState(false); + const [invalidIP, setInvalidIP] = useState(false); + const [updatedBin, setUpdatedBin] = useState(false); + const [freeDiskSpace, setFreeDiskSpace] = useState(''); + + /* Handle yt-dlp update success */ + useEffect(() => { + socket.on('updated', () => { + setUpdatedBin(true) + setHalt(false) + }) + }, []) + + /* Get disk free space */ + useEffect(() => { + socket.on('free-space', (res: string) => { + setFreeDiskSpace(res) + }) + }, []) + + /** + * Update the server ip address state and localstorage whenever the input value changes. + * Validate the ip-addr then set. + * @param e Input change event + */ + const handleAddrChange = (e: React.ChangeEvent) => { + const input = e.target.value; + if (validateIP(input)) { + setInvalidIP(false) + dispatch(setServerAddr(input)) + } else if (validateDomain(input)) { + setInvalidIP(false) + dispatch(setServerAddr(input)) + } else { + setInvalidIP(true) + } + } + + /** + * Language toggler handler + */ + const handleLanguageChage = (event: SelectChangeEvent) => { + dispatch(setLanguage(event.target.value as LanguageUnion)); + } + + /** + * Send via WebSocket a message in order to update the yt-dlp binary from server + */ + const updateBinary = () => { + socket.emit('update-bin') + dispatch(alreadyUpdated()) + } + + + return ( + + + {/* Chart */} + + + + {settings.i18n.t('settingsAnchor')} + + + ws://, + }} + sx={{ mb: 2 }} + /> + + Language + + + dispatch(setCliArgs(settings.cliArgs.toggleNoMTime()))} + /> + } + label={settings.i18n.t('noMTimeCheckbox')} + sx={{ mt: 3 }} + /> + dispatch(setCliArgs(settings.cliArgs.toggleExtractAudio()))} + /> + } + label={settings.i18n.t('extractAudioCheckbox')} + /> + + + + {/* */} + + + + + + + + + ); +} \ No newline at end of file diff --git a/frontend/src/classes.ts b/frontend/src/classes.ts index 4421172..0ab92c3 100644 --- a/frontend/src/classes.ts +++ b/frontend/src/classes.ts @@ -2,25 +2,27 @@ export class CliArguments { private _extractAudio: boolean; private _noMTime: boolean; - constructor() { - this._extractAudio = false; - this._noMTime = false; + constructor(extractAudio = false, noMTime = false) { + this._extractAudio = extractAudio; + this._noMTime = noMTime; } public get extractAudio(): boolean { return this._extractAudio; } - public set extractAudio(v: boolean) { - this._extractAudio = v; + public toggleExtractAudio() { + this._extractAudio = !this._extractAudio; + return this; } public get noMTime(): boolean { return this._noMTime; } - public set noMTime(v: boolean) { - this._noMTime = v; + public toggleNoMTime() { + this._noMTime = !this._noMTime; + return this; } public toString(): string { @@ -37,13 +39,16 @@ export class CliArguments { return args.trim(); } - public fromString(str: string): void { - if (str.includes('-x')) { - this._extractAudio = true; - } + public fromString(str: string): CliArguments { + if (str) { + if (str.includes('-x')) { + this._extractAudio = true; + } - if (str.includes('--no-mtime')) { - this._noMTime = true; + if (str.includes('--no-mtime')) { + this._noMTime = true; + } } + return this; } } \ No newline at end of file diff --git a/frontend/src/components/StackableResult.tsx b/frontend/src/components/StackableResult.tsx index 95750ba..8fbe57b 100644 --- a/frontend/src/components/StackableResult.tsx +++ b/frontend/src/components/StackableResult.tsx @@ -1,53 +1,62 @@ import { Fragment } from "react"; -import { - Row, - Col, - ProgressBar -} from "react-bootstrap"; -import { Badge4kFill, Badge8kFill, BadgeHdFill } from "react-bootstrap-icons"; +import { EightK, FourK, Hd, Sd } from "@mui/icons-material"; +import { Button, Card, CardActionArea, CardActions, CardContent, CardMedia, Chip, Grid, LinearProgress, Skeleton, Stack, Typography } from "@mui/material"; +import { IMessage } from "../interfaces"; +import { ellipsis } from "../utils"; type Props = { - formattedLog: string, + formattedLog: IMessage, title: string, thumbnail: string, resolution: string progress: number, + stopCallback: VoidFunction, } -export function StackableResult({ formattedLog, title, thumbnail, resolution, progress }: Props) { +export function StackableResult({ formattedLog, title, thumbnail, resolution, progress, stopCallback }: Props) { const guessResolution = (xByY: string): JSX.Element => { if (!xByY) return null; - if (xByY.includes('4320')) return (); - if (xByY.includes('2160')) return (); - if (xByY.includes('1080')) return (); - if (xByY.includes('720')) return (); + if (xByY.includes('4320')) return (); + if (xByY.includes('2160')) return (); + if (xByY.includes('1080')) return (); + if (xByY.includes('720')) return (); return null; } return ( - -
- - {title ?

{title}

: null} - -
Status
- {!formattedLog ?
Ready
: null} -
{formattedLog}
- - -
- - -
+ + + {thumbnail ? + : + + } + + + {ellipsis(title, 54)} + + + + {formattedLog.progress} + {formattedLog.dlSpeed} + {formattedLog.size} {guessResolution(resolution)} -
-
-
- {progress ? - : - null - } -
+ + {progress ? + : + null + } + + + + + + ) } \ No newline at end of file diff --git a/frontend/src/features/settings/settingsSlice.ts b/frontend/src/features/settings/settingsSlice.ts new file mode 100644 index 0000000..847682d --- /dev/null +++ b/frontend/src/features/settings/settingsSlice.ts @@ -0,0 +1,50 @@ +import { createSlice, PayloadAction } from "@reduxjs/toolkit" +import { CliArguments } from "../../classes" +import { I18nBuilder } from "../../i18n" + +export type LanguageUnion = "english" | "chinese" | "russian" | "italian" | "spanish" | "korean" +export type ThemeUnion = "light" | "dark" + +export interface SettingsState { + serverAddr: string, + language: LanguageUnion, + theme: ThemeUnion, + cliArgs: CliArguments, + i18n: I18nBuilder +} + +const initialState: SettingsState = { + serverAddr: localStorage.getItem("server-addr") || "localhost", + language: (localStorage.getItem("language") || "english") as LanguageUnion, + theme: (localStorage.getItem("theme") || "light") as ThemeUnion, + cliArgs: localStorage.getItem("cli-args") ? new CliArguments().fromString(localStorage.getItem("cli-args")) : new CliArguments(false, true), + i18n: new I18nBuilder((localStorage.getItem("language") || "english")), +} + +export const settingsSlice = createSlice({ + name: "settings", + initialState, + reducers: { + setServerAddr: (state, action: PayloadAction) => { + state.serverAddr = action.payload + localStorage.setItem("server-addr", action.payload) + }, + setLanguage: (state, action: PayloadAction) => { + state.language = action.payload + state.i18n.setLanguage(action.payload) + localStorage.setItem("language", action.payload) + }, + setCliArgs: (state, action: PayloadAction) => { + state.cliArgs = action.payload + localStorage.setItem("cli-args", action.payload.toString()) + }, + setTheme: (state, action: PayloadAction) => { + state.theme = action.payload + localStorage.setItem("theme", action.payload) + }, + } +}) + +export const { setLanguage, setCliArgs, setTheme, setServerAddr } = settingsSlice.actions + +export default settingsSlice.reducer \ No newline at end of file diff --git a/frontend/src/features/status/statusSlice.ts b/frontend/src/features/status/statusSlice.ts new file mode 100644 index 0000000..9486cc7 --- /dev/null +++ b/frontend/src/features/status/statusSlice.ts @@ -0,0 +1,30 @@ +import { createSlice } from "@reduxjs/toolkit" + +export interface StatusState { + connected: boolean, + updated: boolean, + downloading: boolean, +} + +const initialState: StatusState = { + connected: false, + updated: false, + downloading: false, +} + +export const statusSlice = createSlice({ + name: 'status', + initialState, + reducers: { + connected: (state) => { state.connected = true }, + disconnected: (state) => { state.connected = false }, + updated: (state) => { state.updated = true }, + alreadyUpdated: (state) => { state.updated = false }, + downloading: (state) => { state.downloading = true }, + finished: (state) => { state.downloading = false }, + } +}) + +export const { connected, disconnected, updated, alreadyUpdated, downloading, finished } = statusSlice.actions + +export default statusSlice.reducer \ No newline at end of file diff --git a/frontend/src/stores/store.ts b/frontend/src/stores/store.ts new file mode 100644 index 0000000..33ff206 --- /dev/null +++ b/frontend/src/stores/store.ts @@ -0,0 +1,15 @@ +import { configureStore } from '@reduxjs/toolkit' +import settingsReducer from '../features/settings/settingsSlice' +import statussReducer from '../features/status/statusSlice' + +export const store = configureStore({ + reducer: { + settings: settingsReducer, + status: statussReducer, + }, +}) + +export type RootState = ReturnType + +export type AppDispatch = typeof store.dispatch + diff --git a/frontend/src/utils.ts b/frontend/src/utils.ts index f5d0147..5a9055b 100644 --- a/frontend/src/utils.ts +++ b/frontend/src/utils.ts @@ -59,8 +59,9 @@ export function detectSpeed(str: string): number { */ export const updateInStateMap = (k: number, v: any, target: Map, callback: Function, remove: boolean = false) => { if (remove) { - target.delete(k) - callback(new Map(target)) + const _target = target + _target.delete(k) + callback(new Map(_target)) return; } callback(new Map(target.set(k, v))); diff --git a/package.json b/package.json index 3f0f199..3c0b25e 100644 --- a/package.json +++ b/package.json @@ -18,22 +18,30 @@ "author": "marcobaobao", "license": "ISC", "dependencies": { + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", + "@mui/icons-material": "^5.6.2", + "@mui/material": "^5.6.4", + "@reduxjs/toolkit": "^1.8.1", + "@types/react-router-dom": "^5.3.3", + "babel-plugin-dev-expression": "^0.2.3", "better-sqlite3": "^7.4.5", "react": "^17.0.2", - "react-bootstrap": "2.0.2", - "react-bootstrap-icons": "^1.7.2", "react-dom": "^17.0.2", + "react-redux": "^8.0.1", + "react-router-dom": "^6.3.0", "rxjs": "^7.4.0", "socket.io": "^4.3.2", "socket.io-client": "^4.3.2", - "uuid": "^8.3.2" + "uuid": "^8.3.2", + "vite": "^2.9.8" }, "devDependencies": { - "@parcel/transformer-yaml": "^2.2.1", - "parcel": "^2.0.1", - "typescript": "^4.5.2", + "@parcel/transformer-yaml": "^2.5.0", "@types/better-sqlite3": "^7.4.2", "@types/node": "^17.0.13", - "@types/uuid": "^8.3.4" + "@types/uuid": "^8.3.4", + "parcel": "^2.5.0", + "typescript": "^4.5.2" } } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3366df1..0269fd0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,34 +1,52 @@ lockfileVersion: 5.3 specifiers: + '@babel/core': ^7.12.0 + '@emotion/react': ^11.9.0 + '@emotion/styled': ^11.8.1 + '@mui/icons-material': ^5.6.2 + '@mui/material': ^5.6.4 '@parcel/transformer-yaml': ^2.2.1 + '@reduxjs/toolkit': ^1.8.1 '@types/better-sqlite3': ^7.4.2 '@types/node': ^17.0.13 + '@types/react-router-dom': ^5.3.3 '@types/uuid': ^8.3.4 + babel-plugin-dev-expression: ^0.2.3 better-sqlite3: ^7.4.5 parcel: ^2.0.1 react: ^17.0.2 - react-bootstrap: 2.0.2 - react-bootstrap-icons: ^1.7.2 react-dom: ^17.0.2 + react-redux: ^8.0.1 + react-router-dom: ^6.3.0 rxjs: ^7.4.0 socket.io: ^4.3.2 socket.io-client: ^4.3.2 typescript: ^4.5.2 uuid: ^8.3.2 + vite: ^2.9.8 dependencies: + '@emotion/react': 11.9.0_@babel+core@7.17.10+react@17.0.2 + '@emotion/styled': 11.8.1_2df323fb98de56c4ac988a0e35110d2c + '@mui/icons-material': 5.6.2_@mui+material@5.6.4+react@17.0.2 + '@mui/material': 5.6.4_8a1592cdd44bb6265a8be2c927d84cf2 + '@reduxjs/toolkit': 1.8.1_react-redux@8.0.1+react@17.0.2 + '@types/react-router-dom': 5.3.3 + babel-plugin-dev-expression: 0.2.3_@babel+core@7.17.10 better-sqlite3: 7.5.0 react: 17.0.2 - react-bootstrap: 2.0.2_react-dom@17.0.2+react@17.0.2 - react-bootstrap-icons: 1.7.2_react@17.0.2 react-dom: 17.0.2_react@17.0.2 + react-redux: 8.0.1_react-dom@17.0.2+react@17.0.2 + react-router-dom: 6.3.0_react-dom@17.0.2+react@17.0.2 rxjs: 7.5.2 socket.io: 4.4.1 socket.io-client: 4.4.1 uuid: 8.3.2 + vite: 2.9.8 devDependencies: + '@babel/core': 7.17.10 '@parcel/transformer-yaml': 2.2.1 '@types/better-sqlite3': 7.4.2 '@types/node': 17.0.13 @@ -38,37 +56,49 @@ devDependencies: packages: + /@ampproject/remapping/2.2.0: + resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.1.1 + '@jridgewell/trace-mapping': 0.3.9 + dev: true + /@babel/code-frame/7.16.7: resolution: {integrity: sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==} engines: {node: '>=6.9.0'} dependencies: '@babel/highlight': 7.16.10 - dev: true /@babel/compat-data/7.16.8: resolution: {integrity: sha512-m7OkX0IdKLKPpBlJtF561YJal5y/jyI5fNfWbPxh2D/nbzzGI4qRyrD8xO2jB24u7l+5I2a43scCG2IrfjC50Q==} engines: {node: '>=6.9.0'} dev: true - /@babel/core/7.16.12: - resolution: {integrity: sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg==} + /@babel/compat-data/7.17.10: + resolution: {integrity: sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/core/7.17.10: + resolution: {integrity: sha512-liKoppandF3ZcBnIYFjfSDHZLKdLHGJRkoWtG8zQyGJBQfIYobpnVGI5+pLBNtS6psFLDzyq8+h5HiVljW9PNA==} engines: {node: '>=6.9.0'} dependencies: + '@ampproject/remapping': 2.2.0 '@babel/code-frame': 7.16.7 - '@babel/generator': 7.16.8 - '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.16.12 - '@babel/helper-module-transforms': 7.16.7 - '@babel/helpers': 7.16.7 - '@babel/parser': 7.16.12 + '@babel/generator': 7.17.10 + '@babel/helper-compilation-targets': 7.17.10_@babel+core@7.17.10 + '@babel/helper-module-transforms': 7.17.7 + '@babel/helpers': 7.17.9 + '@babel/parser': 7.17.10 '@babel/template': 7.16.7 - '@babel/traverse': 7.16.10 - '@babel/types': 7.16.8 + '@babel/traverse': 7.17.10 + '@babel/types': 7.17.10 convert-source-map: 1.8.0 debug: 4.3.3 gensync: 1.0.0-beta.2 - json5: 2.2.0 + json5: 2.2.1 semver: 6.3.0 - source-map: 0.5.7 transitivePeerDependencies: - supports-color dev: true @@ -82,19 +112,41 @@ packages: source-map: 0.5.7 dev: true - /@babel/helper-compilation-targets/7.16.7_@babel+core@7.16.12: + /@babel/generator/7.17.10: + resolution: {integrity: sha512-46MJZZo9y3o4kmhBVc7zW7i8dtR1oIK/sdO5NcfcZRhTGYi+KKJRtHNgsU6c4VUcJmUNV/LQdebD/9Dlv4K+Tg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.17.10 + '@jridgewell/gen-mapping': 0.1.1 + jsesc: 2.5.2 + dev: true + + /@babel/helper-compilation-targets/7.16.7_@babel+core@7.17.10: resolution: {integrity: sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: '@babel/compat-data': 7.16.8 - '@babel/core': 7.16.12 + '@babel/core': 7.17.10 '@babel/helper-validator-option': 7.16.7 browserslist: 4.19.1 semver: 6.3.0 dev: true + /@babel/helper-compilation-targets/7.17.10_@babel+core@7.17.10: + resolution: {integrity: sha512-gh3RxjWbauw/dFiU/7whjd0qN9K6nPJMqe6+Er7rOavFh0CQUSwhAE3IcTho2rywPJFxej6TUUHDkWcYI6gGqQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/compat-data': 7.17.10 + '@babel/core': 7.17.10 + '@babel/helper-validator-option': 7.16.7 + browserslist: 4.20.3 + semver: 6.3.0 + dev: true + /@babel/helper-environment-visitor/7.16.7: resolution: {integrity: sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==} engines: {node: '>=6.9.0'} @@ -111,6 +163,14 @@ packages: '@babel/types': 7.16.8 dev: true + /@babel/helper-function-name/7.17.9: + resolution: {integrity: sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.16.7 + '@babel/types': 7.17.10 + dev: true + /@babel/helper-get-function-arity/7.16.7: resolution: {integrity: sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==} engines: {node: '>=6.9.0'} @@ -130,20 +190,19 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.16.8 - dev: true - /@babel/helper-module-transforms/7.16.7: - resolution: {integrity: sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==} + /@babel/helper-module-transforms/7.17.7: + resolution: {integrity: sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==} engines: {node: '>=6.9.0'} dependencies: '@babel/helper-environment-visitor': 7.16.7 '@babel/helper-module-imports': 7.16.7 - '@babel/helper-simple-access': 7.16.7 + '@babel/helper-simple-access': 7.17.7 '@babel/helper-split-export-declaration': 7.16.7 '@babel/helper-validator-identifier': 7.16.7 '@babel/template': 7.16.7 - '@babel/traverse': 7.16.10 - '@babel/types': 7.16.8 + '@babel/traverse': 7.17.10 + '@babel/types': 7.17.10 transitivePeerDependencies: - supports-color dev: true @@ -151,13 +210,12 @@ packages: /@babel/helper-plugin-utils/7.16.7: resolution: {integrity: sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==} engines: {node: '>=6.9.0'} - dev: true - /@babel/helper-simple-access/7.16.7: - resolution: {integrity: sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==} + /@babel/helper-simple-access/7.17.7: + resolution: {integrity: sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.16.8 + '@babel/types': 7.17.10 dev: true /@babel/helper-split-export-declaration/7.16.7: @@ -170,20 +228,19 @@ packages: /@babel/helper-validator-identifier/7.16.7: resolution: {integrity: sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==} engines: {node: '>=6.9.0'} - dev: true /@babel/helper-validator-option/7.16.7: resolution: {integrity: sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==} engines: {node: '>=6.9.0'} dev: true - /@babel/helpers/7.16.7: - resolution: {integrity: sha512-9ZDoqtfY7AuEOt3cxchfii6C7GDyyMBffktR5B2jvWv8u2+efwvpnVKXMWzNehqy68tKgAfSwfdw/lWpthS2bw==} + /@babel/helpers/7.17.9: + resolution: {integrity: sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q==} engines: {node: '>=6.9.0'} dependencies: '@babel/template': 7.16.7 - '@babel/traverse': 7.16.10 - '@babel/types': 7.16.8 + '@babel/traverse': 7.17.10 + '@babel/types': 7.17.10 transitivePeerDependencies: - supports-color dev: true @@ -195,7 +252,6 @@ packages: '@babel/helper-validator-identifier': 7.16.7 chalk: 2.4.2 js-tokens: 4.0.0 - dev: true /@babel/parser/7.16.12: resolution: {integrity: sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A==} @@ -203,25 +259,41 @@ packages: hasBin: true dev: true - /@babel/plugin-syntax-flow/7.16.7_@babel+core@7.16.12: + /@babel/parser/7.17.10: + resolution: {integrity: sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ==} + engines: {node: '>=6.0.0'} + hasBin: true + dev: true + + /@babel/plugin-syntax-flow/7.16.7_@babel+core@7.17.10: resolution: {integrity: sha512-UDo3YGQO0jH6ytzVwgSLv9i/CzMcUjbKenL67dTrAZPPv6GFAtDhe6jqnvmoKzC/7htNTohhos+onPtDMqJwaQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.12 + '@babel/core': 7.17.10 '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-flow-strip-types/7.16.7_@babel+core@7.16.12: + /@babel/plugin-syntax-jsx/7.16.7_@babel+core@7.17.10: + resolution: {integrity: sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.17.10 + '@babel/helper-plugin-utils': 7.16.7 + dev: false + + /@babel/plugin-transform-flow-strip-types/7.16.7_@babel+core@7.17.10: resolution: {integrity: sha512-mzmCq3cNsDpZZu9FADYYyfZJIOrSONmHcop2XEKPdBNMa4PDC4eEvcOvzZaCNcjKu72v0XQlA5y1g58aLRXdYg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.16.12 + '@babel/core': 7.17.10 '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-syntax-flow': 7.16.7_@babel+core@7.16.12 + '@babel/plugin-syntax-flow': 7.16.7_@babel+core@7.17.10 dev: true /@babel/runtime/7.16.7: @@ -231,13 +303,20 @@ packages: regenerator-runtime: 0.13.9 dev: false + /@babel/runtime/7.17.9: + resolution: {integrity: sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.13.9 + dev: false + /@babel/template/7.16.7: resolution: {integrity: sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==} engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.16.7 - '@babel/parser': 7.16.12 - '@babel/types': 7.16.8 + '@babel/parser': 7.17.10 + '@babel/types': 7.17.10 dev: true /@babel/traverse/7.16.10: @@ -258,18 +337,351 @@ packages: - supports-color dev: true + /@babel/traverse/7.17.10: + resolution: {integrity: sha512-VmbrTHQteIdUUQNTb+zE12SHS/xQVIShmBPhlNP12hD5poF2pbITW1Z4172d03HegaQWhLffdkRJYtAzp0AGcw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.16.7 + '@babel/generator': 7.17.10 + '@babel/helper-environment-visitor': 7.16.7 + '@babel/helper-function-name': 7.17.9 + '@babel/helper-hoist-variables': 7.16.7 + '@babel/helper-split-export-declaration': 7.16.7 + '@babel/parser': 7.17.10 + '@babel/types': 7.17.10 + debug: 4.3.3 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/types/7.16.8: resolution: {integrity: sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg==} engines: {node: '>=6.9.0'} dependencies: '@babel/helper-validator-identifier': 7.16.7 to-fast-properties: 2.0.0 + + /@babel/types/7.17.10: + resolution: {integrity: sha512-9O26jG0mBYfGkUYCYZRnBwbVLd1UZOICEr2Em6InB6jVfsAv1GKgwXHmrSg+WFWDmeKTA6vyTZiN8tCSM5Oo3A==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.16.7 + to-fast-properties: 2.0.0 dev: true + /@emotion/babel-plugin/11.9.2_@babel+core@7.17.10: + resolution: {integrity: sha512-Pr/7HGH6H6yKgnVFNEj2MVlreu3ADqftqjqwUvDy/OJzKFgxKeTQ+eeUf20FOTuHVkDON2iNa25rAXVYtWJCjw==} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.17.10 + '@babel/helper-module-imports': 7.16.7 + '@babel/plugin-syntax-jsx': 7.16.7_@babel+core@7.17.10 + '@babel/runtime': 7.16.7 + '@emotion/hash': 0.8.0 + '@emotion/memoize': 0.7.5 + '@emotion/serialize': 1.0.3 + babel-plugin-macros: 2.8.0 + convert-source-map: 1.8.0 + escape-string-regexp: 4.0.0 + find-root: 1.1.0 + source-map: 0.5.7 + stylis: 4.0.13 + dev: false + + /@emotion/cache/11.7.1: + resolution: {integrity: sha512-r65Zy4Iljb8oyjtLeCuBH8Qjiy107dOYC6SJq7g7GV5UCQWMObY4SJDPGFjiiVpPrOJ2hmJOoBiYTC7hwx9E2A==} + dependencies: + '@emotion/memoize': 0.7.5 + '@emotion/sheet': 1.1.0 + '@emotion/utils': 1.1.0 + '@emotion/weak-memoize': 0.2.5 + stylis: 4.0.13 + dev: false + + /@emotion/hash/0.8.0: + resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==} + dev: false + + /@emotion/is-prop-valid/1.1.2: + resolution: {integrity: sha512-3QnhqeL+WW88YjYbQL5gUIkthuMw7a0NGbZ7wfFVk2kg/CK5w8w5FFa0RzWjyY1+sujN0NWbtSHH6OJmWHtJpQ==} + dependencies: + '@emotion/memoize': 0.7.5 + dev: false + + /@emotion/memoize/0.7.5: + resolution: {integrity: sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ==} + dev: false + + /@emotion/react/11.9.0_@babel+core@7.17.10+react@17.0.2: + resolution: {integrity: sha512-lBVSF5d0ceKtfKCDQJveNAtkC7ayxpVlgOohLgXqRwqWr9bOf4TZAFFyIcNngnV6xK6X4x2ZeXq7vliHkoVkxQ==} + peerDependencies: + '@babel/core': ^7.0.0 + '@types/react': '*' + react: '>=16.8.0' + peerDependenciesMeta: + '@babel/core': + optional: true + '@types/react': + optional: true + dependencies: + '@babel/core': 7.17.10 + '@babel/runtime': 7.16.7 + '@emotion/babel-plugin': 11.9.2_@babel+core@7.17.10 + '@emotion/cache': 11.7.1 + '@emotion/serialize': 1.0.3 + '@emotion/utils': 1.1.0 + '@emotion/weak-memoize': 0.2.5 + hoist-non-react-statics: 3.3.2 + react: 17.0.2 + dev: false + + /@emotion/serialize/1.0.3: + resolution: {integrity: sha512-2mSSvgLfyV3q+iVh3YWgNlUc2a9ZlDU7DjuP5MjK3AXRR0dYigCrP99aeFtaB2L/hjfEZdSThn5dsZ0ufqbvsA==} + dependencies: + '@emotion/hash': 0.8.0 + '@emotion/memoize': 0.7.5 + '@emotion/unitless': 0.7.5 + '@emotion/utils': 1.1.0 + csstype: 3.0.11 + dev: false + + /@emotion/sheet/1.1.0: + resolution: {integrity: sha512-u0AX4aSo25sMAygCuQTzS+HsImZFuS8llY8O7b9MDRzbJM0kVJlAz6KNDqcG7pOuQZJmj/8X/rAW+66kMnMW+g==} + dev: false + + /@emotion/styled/11.8.1_2df323fb98de56c4ac988a0e35110d2c: + resolution: {integrity: sha512-OghEVAYBZMpEquHZwuelXcRjRJQOVayvbmNR0zr174NHdmMgrNkLC6TljKC5h9lZLkN5WGrdUcrKlOJ4phhoTQ==} + peerDependencies: + '@babel/core': ^7.0.0 + '@emotion/react': ^11.0.0-rc.0 + '@types/react': '*' + react: '>=16.8.0' + peerDependenciesMeta: + '@babel/core': + optional: true + '@types/react': + optional: true + dependencies: + '@babel/core': 7.17.10 + '@babel/runtime': 7.16.7 + '@emotion/babel-plugin': 11.9.2_@babel+core@7.17.10 + '@emotion/is-prop-valid': 1.1.2 + '@emotion/react': 11.9.0_@babel+core@7.17.10+react@17.0.2 + '@emotion/serialize': 1.0.3 + '@emotion/utils': 1.1.0 + react: 17.0.2 + dev: false + + /@emotion/unitless/0.7.5: + resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} + dev: false + + /@emotion/utils/1.1.0: + resolution: {integrity: sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ==} + dev: false + + /@emotion/weak-memoize/0.2.5: + resolution: {integrity: sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==} + dev: false + /@iarna/toml/2.2.5: resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==} dev: true + /@jridgewell/gen-mapping/0.1.1: + resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.1.0 + '@jridgewell/sourcemap-codec': 1.4.12 + dev: true + + /@jridgewell/resolve-uri/3.0.6: + resolution: {integrity: sha512-R7xHtBSNm+9SyvpJkdQl+qrM3Hm2fea3Ef197M3mUug+v+yR+Rhfbs7PBtcBUVnIWJ4JcAdjvij+c8hXS9p5aw==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/set-array/1.1.0: + resolution: {integrity: sha512-SfJxIxNVYLTsKwzB3MoOQ1yxf4w/E6MdkvTgrgAt1bfxjSrLUoHMKrDOykwN14q65waezZIdqDneUIPh4/sKxg==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/sourcemap-codec/1.4.12: + resolution: {integrity: sha512-az/NhpIwP3K33ILr0T2bso+k2E/SLf8Yidd8mHl0n6sCQ4YdyC8qDhZA6kOPDNDBA56ZnIjngVl0U3jREA0BUA==} + dev: true + + /@jridgewell/trace-mapping/0.3.9: + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + dependencies: + '@jridgewell/resolve-uri': 3.0.6 + '@jridgewell/sourcemap-codec': 1.4.12 + dev: true + + /@mui/base/5.0.0-alpha.79_react-dom@17.0.2+react@17.0.2: + resolution: {integrity: sha512-/lZLF027BkiEjM8MIYoeS/FEhTKf+41ePU9SOijMGrCin1Y0Igucw+IHa1fF8HXD7wDbFKqHuso3J1jMG8wyNw==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.17.9 + '@emotion/is-prop-valid': 1.1.2 + '@mui/types': 7.1.3 + '@mui/utils': 5.6.1_react@17.0.2 + '@popperjs/core': 2.11.5 + clsx: 1.1.1 + prop-types: 15.8.1 + react: 17.0.2 + react-dom: 17.0.2_react@17.0.2 + react-is: 17.0.2 + dev: false + + /@mui/icons-material/5.6.2_@mui+material@5.6.4+react@17.0.2: + resolution: {integrity: sha512-9QdI7axKuBAyaGz4mtdi7Uy1j73/thqFmEuxpJHxNC7O8ADEK1Da3t2veK2tgmsXsUlAHcAG63gg+GvWWeQNqQ==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@mui/material': ^5.0.0 + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.17.9 + '@mui/material': 5.6.4_8a1592cdd44bb6265a8be2c927d84cf2 + react: 17.0.2 + dev: false + + /@mui/material/5.6.4_8a1592cdd44bb6265a8be2c927d84cf2: + resolution: {integrity: sha512-7TD+u/SExZK2a55w6reX56oPk37gKr/M/XGt156X+m0d9LhzOsW864nkErIX/H8oSkX/6kCimxu1FDsO+gjiVw==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@emotion/react': ^11.5.0 + '@emotion/styled': ^11.3.0 + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.17.9 + '@emotion/react': 11.9.0_@babel+core@7.17.10+react@17.0.2 + '@emotion/styled': 11.8.1_2df323fb98de56c4ac988a0e35110d2c + '@mui/base': 5.0.0-alpha.79_react-dom@17.0.2+react@17.0.2 + '@mui/system': 5.6.4_09a0c9559c3e7c8c898f158921333fde + '@mui/types': 7.1.3 + '@mui/utils': 5.6.1_react@17.0.2 + '@types/react-transition-group': 4.4.4 + clsx: 1.1.1 + csstype: 3.0.11 + hoist-non-react-statics: 3.3.2 + prop-types: 15.8.1 + react: 17.0.2 + react-dom: 17.0.2_react@17.0.2 + react-is: 17.0.2 + react-transition-group: 4.4.2_react-dom@17.0.2+react@17.0.2 + dev: false + + /@mui/private-theming/5.6.2_react@17.0.2: + resolution: {integrity: sha512-IbrSfFXfiZdyhRMC2bgGTFtb16RBQ5mccmjeh3MtAERWuepiCK7gkW5D9WhEsfTu6iez+TEjeUKSgmMHlsM2mg==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.17.9 + '@mui/utils': 5.6.1_react@17.0.2 + prop-types: 15.8.1 + react: 17.0.2 + dev: false + + /@mui/styled-engine/5.6.1_09a0c9559c3e7c8c898f158921333fde: + resolution: {integrity: sha512-jEhH6TBY8jc9S8yVncXmoTYTbATjEu44RMFXj6sIYfKr5NArVwTwRo3JexLL0t3BOAiYM4xsFLgfKEIvB9SAeQ==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@emotion/react': ^11.4.1 + '@emotion/styled': ^11.3.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + dependencies: + '@babel/runtime': 7.17.9 + '@emotion/cache': 11.7.1 + '@emotion/react': 11.9.0_@babel+core@7.17.10+react@17.0.2 + '@emotion/styled': 11.8.1_2df323fb98de56c4ac988a0e35110d2c + prop-types: 15.8.1 + react: 17.0.2 + dev: false + + /@mui/system/5.6.4_09a0c9559c3e7c8c898f158921333fde: + resolution: {integrity: sha512-7rsWED1wMFMePySJobsBerFZNu7ga580QSi3Zd6sJR8nVj12qD3yIdfvxA70/PxJ/805KbIT0GX7edKI+hpyhA==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@emotion/react': ^11.5.0 + '@emotion/styled': ^11.3.0 + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.17.9 + '@emotion/react': 11.9.0_@babel+core@7.17.10+react@17.0.2 + '@emotion/styled': 11.8.1_2df323fb98de56c4ac988a0e35110d2c + '@mui/private-theming': 5.6.2_react@17.0.2 + '@mui/styled-engine': 5.6.1_09a0c9559c3e7c8c898f158921333fde + '@mui/types': 7.1.3 + '@mui/utils': 5.6.1_react@17.0.2 + clsx: 1.1.1 + csstype: 3.0.11 + prop-types: 15.8.1 + react: 17.0.2 + dev: false + + /@mui/types/7.1.3: + resolution: {integrity: sha512-DDF0UhMBo4Uezlk+6QxrlDbchF79XG6Zs0zIewlR4c0Dt6GKVFfUtzPtHCH1tTbcSlq/L2bGEdiaoHBJ9Y1gSA==} + peerDependencies: + '@types/react': '*' + peerDependenciesMeta: + '@types/react': + optional: true + dev: false + + /@mui/utils/5.6.1_react@17.0.2: + resolution: {integrity: sha512-CPrzrkiBusCZBLWu0Sg5MJvR3fKJyK3gKecLVX012LULyqg2U64Oz04BKhfkbtBrPBbSQxM+DWW9B1c9hmV9nQ==} + engines: {node: '>=12.0.0'} + peerDependencies: + react: ^17.0.0 || ^18.0.0 + dependencies: + '@babel/runtime': 7.17.9 + '@types/prop-types': 15.7.4 + '@types/react-is': 17.0.3 + prop-types: 15.8.1 + react: 17.0.2 + react-is: 17.0.2 + dev: false + /@nodelib/fs.scandir/2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -849,10 +1261,10 @@ packages: resolution: {integrity: sha512-eNQTmnsiY2ycuGgr3tu5BfR6rz9WGhb6psz+cZkIbfZp0xaJaovTftjT5jR4clsDO/+dX5cM8KOUuJm5MYXRjg==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: - '@babel/core': 7.16.12 + '@babel/core': 7.17.10 '@babel/generator': 7.16.8 - '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-flow-strip-types': 7.16.7_@babel+core@7.16.12 + '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.17.10 + '@babel/plugin-transform-flow-strip-types': 7.16.7_@babel+core@7.17.10 '@babel/traverse': 7.16.10 '@parcel/babel-ast-utils': 2.2.1 '@parcel/diagnostic': 2.2.1 @@ -1084,63 +1496,27 @@ packages: nullthrows: 1.1.1 dev: true - /@popperjs/core/2.11.2: - resolution: {integrity: sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA==} + /@popperjs/core/2.11.5: + resolution: {integrity: sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==} dev: false - /@react-aria/ssr/3.1.0_react@17.0.2: - resolution: {integrity: sha512-RxqQKmE8sO7TGdrcSlHTcVzMP450hqowtBSd2bBS9oPlcokVkaGq28c3Rwa8ty5ctw4EBCjXqjP7xdcKMGDzug==} + /@reduxjs/toolkit/1.8.1_react-redux@8.0.1+react@17.0.2: + resolution: {integrity: sha512-Q6mzbTpO9nOYRnkwpDlFOAbQnd3g7zj7CtHAZWz5SzE5lcV97Tf8f3SzOO8BoPOMYBFgfZaqTUZqgGu+a0+Fng==} peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 + react: ^16.9.0 || ^17.0.0 || ^18 + react-redux: ^7.2.1 || ^8.0.0-beta + peerDependenciesMeta: + react: + optional: true + react-redux: + optional: true dependencies: - '@babel/runtime': 7.16.7 + immer: 9.0.12 react: 17.0.2 - dev: false - - /@restart/context/2.1.4_react@17.0.2: - resolution: {integrity: sha512-INJYZQJP7g+IoDUh/475NlGiTeMfwTXUEr3tmRneckHIxNolGOW9CTq83S8cxq0CgJwwcMzMJFchxvlwe7Rk8Q==} - peerDependencies: - react: '>=16.3.2' - dependencies: - react: 17.0.2 - dev: false - - /@restart/hooks/0.3.27_react@17.0.2: - resolution: {integrity: sha512-s984xV/EapUIfkjlf8wz9weP2O9TNKR96C68FfMEy2bE69+H4cNv3RD4Mf97lW7Htt7PjZrYTjSC8f3SB9VCXw==} - peerDependencies: - react: '>=16.8.0' - dependencies: - dequal: 2.0.2 - react: 17.0.2 - dev: false - - /@restart/hooks/0.4.5_react@17.0.2: - resolution: {integrity: sha512-tLGtY0aHeIfT7aPwUkvQuhIy3+q3w4iqmUzFLPlOAf/vNUacLaBt1j/S//jv/dQhenRh8jvswyMojCwmLvJw8A==} - peerDependencies: - react: '>=16.8.0' - dependencies: - dequal: 2.0.2 - react: 17.0.2 - dev: false - - /@restart/ui/0.2.6_react-dom@17.0.2+react@17.0.2: - resolution: {integrity: sha512-lcutEWPvsxz0uEyRxuysCbHBfXDFnMKNMNTsnuPmLFjZXgW9fVmhksS6rpFklXHMwxOM9g6hRTBq0gS3QRKgzQ==} - peerDependencies: - react: '>=16.14.0' - react-dom: '>=16.14.0' - dependencies: - '@babel/runtime': 7.16.7 - '@popperjs/core': 2.11.2 - '@react-aria/ssr': 3.1.0_react@17.0.2 - '@restart/hooks': 0.4.5_react@17.0.2 - '@types/warning': 3.0.0 - dequal: 2.0.2 - dom-helpers: 5.2.1 - prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - uncontrollable: 7.2.1_react@17.0.2 - warning: 4.0.3 + react-redux: 8.0.1_react-dom@17.0.2+react@17.0.2 + redux: 4.2.0 + redux-thunk: 2.4.1_redux@4.2.0 + reselect: 4.1.5 dev: false /@socket.io/base64-arraybuffer/1.0.2: @@ -1179,27 +1555,54 @@ packages: resolution: {integrity: sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==} dev: false + /@types/history/4.7.11: + resolution: {integrity: sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==} + dev: false + + /@types/hoist-non-react-statics/3.3.1: + resolution: {integrity: sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==} + dependencies: + '@types/react': 17.0.38 + hoist-non-react-statics: 3.3.2 + dev: false + /@types/http-proxy/1.17.8: resolution: {integrity: sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==} dependencies: '@types/node': 17.0.13 dev: true - /@types/invariant/2.2.35: - resolution: {integrity: sha512-DxX1V9P8zdJPYQat1gHyY0xj3efl8gnMVjiM9iCY6y27lj+PoQWkgjt8jDqmovPqULkKVpKRg8J36iQiA+EtEg==} - dev: false - /@types/node/17.0.13: resolution: {integrity: sha512-Y86MAxASe25hNzlDbsviXl8jQHb0RDvKt4c40ZJQ1Don0AAL0STLZSs4N+6gLEO55pedy7r2cLwS+ZDxPm/2Bw==} /@types/parse-json/4.0.0: resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} - dev: true /@types/prop-types/15.7.4: resolution: {integrity: sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==} dev: false + /@types/react-is/17.0.3: + resolution: {integrity: sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==} + dependencies: + '@types/react': 17.0.38 + dev: false + + /@types/react-router-dom/5.3.3: + resolution: {integrity: sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==} + dependencies: + '@types/history': 4.7.11 + '@types/react': 17.0.38 + '@types/react-router': 5.1.18 + dev: false + + /@types/react-router/5.1.18: + resolution: {integrity: sha512-YYknwy0D0iOwKQgz9v8nOzt2J6l4gouBmDnWqUUznltOTaon+r8US8ky8HvN0tXvc38U9m6z/t2RsVsnd1zM0g==} + dependencies: + '@types/history': 4.7.11 + '@types/react': 17.0.38 + dev: false + /@types/react-transition-group/4.4.4: resolution: {integrity: sha512-7gAPz7anVK5xzbeQW9wFBDg7G++aPLAFY0QaSMOou9rJZpbuI58WAuJrgu+qR92l61grlnCUe7AFX8KGahAgug==} dependencies: @@ -1218,14 +1621,14 @@ packages: resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==} dev: false + /@types/use-sync-external-store/0.0.3: + resolution: {integrity: sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==} + dev: false + /@types/uuid/8.3.4: resolution: {integrity: sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==} dev: true - /@types/warning/3.0.0: - resolution: {integrity: sha1-DSUBJorY+ZYrdA04fEZU9fjiPlI=} - dev: false - /abortcontroller-polyfill/1.7.3: resolution: {integrity: sha512-zetDJxd89y3X99Kvo4qFx8GKlt6GsvN3UcRZHwU6iFA/0KiOmhkTVhe8oRoTBiTVPZu09x3vCra47+w8Yz1+2Q==} dev: true @@ -1266,7 +1669,6 @@ packages: engines: {node: '>=4'} dependencies: color-convert: 1.9.3 - dev: true /ansi-styles/4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} @@ -1329,6 +1731,22 @@ packages: engines: {node: '>= 0.4'} dev: true + /babel-plugin-dev-expression/0.2.3_@babel+core@7.17.10: + resolution: {integrity: sha512-rP5LK9QQTzCW61nVVzw88En1oK8t8gTsIeC6E61oelxNsU842yMjF0G1MxhvUpCkxCEIj7sE8/e5ieTheT//uw==} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.17.10 + dev: false + + /babel-plugin-macros/2.8.0: + resolution: {integrity: sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==} + dependencies: + '@babel/runtime': 7.17.9 + cosmiconfig: 6.0.0 + resolve: 1.22.0 + dev: false + /backo2/1.0.2: resolution: {integrity: sha1-MasayLEpNjRj41s+u2n038+6eUc=} dev: false @@ -1469,6 +1887,18 @@ packages: picocolors: 1.0.0 dev: true + /browserslist/4.20.3: + resolution: {integrity: sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001336 + electron-to-chromium: 1.4.134 + escalade: 3.1.1 + node-releases: 2.0.4 + picocolors: 1.0.0 + dev: true + /buffer-from/1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} dev: true @@ -1502,7 +1932,6 @@ packages: /callsites/3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - dev: true /caniuse-api/3.0.0: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} @@ -1517,6 +1946,10 @@ packages: resolution: {integrity: sha512-csfD/GpHMqgEL3V3uIgosvh+SVIQvCh43SNu9HRbP1lnxkKm1kjDG4f32PP571JplkLjfS+mg2p1gxR7MYrrIA==} dev: true + /caniuse-lite/1.0.30001336: + resolution: {integrity: sha512-/YxSlBmL7iKXTbIJ48IQTnAOBk7XmWsxhBF1PZLOko5Dt9qc4Pl+84lfqG3Tc4EuavurRn1QLoVJGxY2iSycfw==} + dev: true + /chalk/2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -1524,7 +1957,6 @@ packages: ansi-styles: 3.2.1 escape-string-regexp: 1.0.5 supports-color: 5.5.0 - dev: true /chalk/4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} @@ -1550,10 +1982,6 @@ packages: safe-buffer: 5.2.1 dev: true - /classnames/2.3.1: - resolution: {integrity: sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==} - dev: false - /cli-cursor/3.1.0: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} engines: {node: '>=8'} @@ -1576,6 +2004,11 @@ packages: engines: {node: '>=0.8'} dev: true + /clsx/1.1.1: + resolution: {integrity: sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==} + engines: {node: '>=6'} + dev: false + /code-point-at/1.1.0: resolution: {integrity: sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=} engines: {node: '>=0.10.0'} @@ -1585,7 +2018,6 @@ packages: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: color-name: 1.1.3 - dev: true /color-convert/2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} @@ -1596,7 +2028,6 @@ packages: /color-name/1.1.3: resolution: {integrity: sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=} - dev: true /color-name/1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} @@ -1658,7 +2089,6 @@ packages: resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==} dependencies: safe-buffer: 5.1.2 - dev: true /cookie/0.4.1: resolution: {integrity: sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==} @@ -1681,6 +2111,17 @@ packages: vary: 1.1.2 dev: false + /cosmiconfig/6.0.0: + resolution: {integrity: sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==} + engines: {node: '>=8'} + dependencies: + '@types/parse-json': 4.0.0 + import-fresh: 3.3.0 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + dev: false + /cosmiconfig/7.0.1: resolution: {integrity: sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==} engines: {node: '>=10'} @@ -1856,6 +2297,10 @@ packages: resolution: {integrity: sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==} dev: false + /csstype/3.0.11: + resolution: {integrity: sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==} + dev: false + /debug/2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} dependencies: @@ -1902,11 +2347,6 @@ packages: resolution: {integrity: sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=} dev: false - /dequal/2.0.2: - resolution: {integrity: sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug==} - engines: {node: '>=6'} - dev: false - /des.js/1.0.1: resolution: {integrity: sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==} dependencies: @@ -1930,7 +2370,7 @@ packages: /dom-helpers/5.2.1: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} dependencies: - '@babel/runtime': 7.16.7 + '@babel/runtime': 7.17.9 csstype: 3.0.10 dev: false @@ -1987,6 +2427,10 @@ packages: jake: 10.8.2 dev: true + /electron-to-chromium/1.4.134: + resolution: {integrity: sha512-OdD7M2no4Mi8PopfvoOuNcwYDJ2mNFxaBfurA6okG3fLBaMcFah9S+si84FhX+FIWLKkdaiHfl4A+5ep/gOVrg==} + dev: true + /electron-to-chromium/1.4.52: resolution: {integrity: sha512-JGkh8HEh5PnVrhU4HbpyyO0O791dVY6k7AdqfDeqbcRMeoGxtNHWT77deR2nhvbLe4dKpxjlDEvdEwrvRLGu2Q==} dev: true @@ -2084,7 +2528,6 @@ packages: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} dependencies: is-arrayish: 0.2.1 - dev: true /es-abstract/1.19.1: resolution: {integrity: sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==} @@ -2125,6 +2568,214 @@ packages: resolution: {integrity: sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=} dev: true + /esbuild-android-64/0.14.38: + resolution: {integrity: sha512-aRFxR3scRKkbmNuGAK+Gee3+yFxkTJO/cx83Dkyzo4CnQl/2zVSurtG6+G86EQIZ+w+VYngVyK7P3HyTBKu3nw==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /esbuild-android-arm64/0.14.38: + resolution: {integrity: sha512-L2NgQRWuHFI89IIZIlpAcINy9FvBk6xFVZ7xGdOwIm8VyhX1vNCEqUJO3DPSSy945Gzdg98cxtNt8Grv1CsyhA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /esbuild-darwin-64/0.14.38: + resolution: {integrity: sha512-5JJvgXkX87Pd1Og0u/NJuO7TSqAikAcQQ74gyJ87bqWRVeouky84ICoV4sN6VV53aTW+NE87qLdGY4QA2S7KNA==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /esbuild-darwin-arm64/0.14.38: + resolution: {integrity: sha512-eqF+OejMI3mC5Dlo9Kdq/Ilbki9sQBw3QlHW3wjLmsLh+quNfHmGMp3Ly1eWm981iGBMdbtSS9+LRvR2T8B3eQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /esbuild-freebsd-64/0.14.38: + resolution: {integrity: sha512-epnPbhZUt93xV5cgeY36ZxPXDsQeO55DppzsIgWM8vgiG/Rz+qYDLmh5ts3e+Ln1wA9dQ+nZmVHw+RjaW3I5Ig==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + + /esbuild-freebsd-arm64/0.14.38: + resolution: {integrity: sha512-/9icXUYJWherhk+y5fjPI5yNUdFPtXHQlwP7/K/zg8t8lQdHVj20SqU9/udQmeUo5pDFHMYzcEFfJqgOVeKNNQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + + /esbuild-linux-32/0.14.38: + resolution: {integrity: sha512-QfgfeNHRFvr2XeHFzP8kOZVnal3QvST3A0cgq32ZrHjSMFTdgXhMhmWdKzRXP/PKcfv3e2OW9tT9PpcjNvaq6g==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /esbuild-linux-64/0.14.38: + resolution: {integrity: sha512-uuZHNmqcs+Bj1qiW9k/HZU3FtIHmYiuxZ/6Aa+/KHb/pFKr7R3aVqvxlAudYI9Fw3St0VCPfv7QBpUITSmBR1Q==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /esbuild-linux-arm/0.14.38: + resolution: {integrity: sha512-FiFvQe8J3VKTDXG01JbvoVRXQ0x6UZwyrU4IaLBZeq39Bsbatd94Fuc3F1RGqPF5RbIWW7RvkVQjn79ejzysnA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /esbuild-linux-arm64/0.14.38: + resolution: {integrity: sha512-HlMGZTEsBrXrivr64eZ/EO0NQM8H8DuSENRok9d+Jtvq8hOLzrxfsAT9U94K3KOGk2XgCmkaI2KD8hX7F97lvA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /esbuild-linux-mips64le/0.14.38: + resolution: {integrity: sha512-qd1dLf2v7QBiI5wwfil9j0HG/5YMFBAmMVmdeokbNAMbcg49p25t6IlJFXAeLzogv1AvgaXRXvgFNhScYEUXGQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /esbuild-linux-ppc64le/0.14.38: + resolution: {integrity: sha512-mnbEm7o69gTl60jSuK+nn+pRsRHGtDPfzhrqEUXyCl7CTOCLtWN2bhK8bgsdp6J/2NyS/wHBjs1x8aBWwP2X9Q==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /esbuild-linux-riscv64/0.14.38: + resolution: {integrity: sha512-+p6YKYbuV72uikChRk14FSyNJZ4WfYkffj6Af0/Tw63/6TJX6TnIKE+6D3xtEc7DeDth1fjUOEqm+ApKFXbbVQ==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /esbuild-linux-s390x/0.14.38: + resolution: {integrity: sha512-0zUsiDkGJiMHxBQ7JDU8jbaanUY975CdOW1YDrurjrM0vWHfjv9tLQsW9GSyEb/heSK1L5gaweRjzfUVBFoybQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /esbuild-netbsd-64/0.14.38: + resolution: {integrity: sha512-cljBAApVwkpnJZfnRVThpRBGzCi+a+V9Ofb1fVkKhtrPLDYlHLrSYGtmnoTVWDQdU516qYI8+wOgcGZ4XIZh0Q==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: false + optional: true + + /esbuild-openbsd-64/0.14.38: + resolution: {integrity: sha512-CDswYr2PWPGEPpLDUO50mL3WO/07EMjnZDNKpmaxUPsrW+kVM3LoAqr/CE8UbzugpEiflYqJsGPLirThRB18IQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: false + optional: true + + /esbuild-sunos-64/0.14.38: + resolution: {integrity: sha512-2mfIoYW58gKcC3bck0j7lD3RZkqYA7MmujFYmSn9l6TiIcAMpuEvqksO+ntBgbLep/eyjpgdplF7b+4T9VJGOA==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: false + optional: true + + /esbuild-windows-32/0.14.38: + resolution: {integrity: sha512-L2BmEeFZATAvU+FJzJiRLFUP+d9RHN+QXpgaOrs2klshoAm1AE6Us4X6fS9k33Uy5SzScn2TpcgecbqJza1Hjw==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /esbuild-windows-64/0.14.38: + resolution: {integrity: sha512-Khy4wVmebnzue8aeSXLC+6clo/hRYeNIm0DyikoEqX+3w3rcvrhzpoix0S+MF9vzh6JFskkIGD7Zx47ODJNyCw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /esbuild-windows-arm64/0.14.38: + resolution: {integrity: sha512-k3FGCNmHBkqdJXuJszdWciAH77PukEyDsdIryEHn9cKLQFxzhT39dSumeTuggaQcXY57UlmLGIkklWZo2qzHpw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /esbuild/0.14.38: + resolution: {integrity: sha512-12fzJ0fsm7gVZX1YQ1InkOE5f9Tl7cgf6JPYXRJtPIoE0zkWAbHdPHVPPaLi9tYAcEBqheGzqLn/3RdTOyBfcA==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + esbuild-android-64: 0.14.38 + esbuild-android-arm64: 0.14.38 + esbuild-darwin-64: 0.14.38 + esbuild-darwin-arm64: 0.14.38 + esbuild-freebsd-64: 0.14.38 + esbuild-freebsd-arm64: 0.14.38 + esbuild-linux-32: 0.14.38 + esbuild-linux-64: 0.14.38 + esbuild-linux-arm: 0.14.38 + esbuild-linux-arm64: 0.14.38 + esbuild-linux-mips64le: 0.14.38 + esbuild-linux-ppc64le: 0.14.38 + esbuild-linux-riscv64: 0.14.38 + esbuild-linux-s390x: 0.14.38 + esbuild-netbsd-64: 0.14.38 + esbuild-openbsd-64: 0.14.38 + esbuild-sunos-64: 0.14.38 + esbuild-windows-32: 0.14.38 + esbuild-windows-64: 0.14.38 + esbuild-windows-arm64: 0.14.38 + dev: false + /escalade/3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -2137,7 +2788,11 @@ packages: /escape-string-regexp/1.0.5: resolution: {integrity: sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=} engines: {node: '>=0.8.0'} - dev: true + + /escape-string-regexp/4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + dev: false /esprima/4.0.1: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} @@ -2234,6 +2889,10 @@ packages: unpipe: 1.0.0 dev: true + /find-root/1.1.0: + resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} + dev: false + /follow-redirects/1.14.7: resolution: {integrity: sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==} engines: {node: '>=4.0'} @@ -2261,9 +2920,16 @@ packages: resolution: {integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8=} dev: true + /fsevents/2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: false + optional: true + /function-bind/1.1.1: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - dev: true /gauge/2.7.4: resolution: {integrity: sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=} @@ -2359,7 +3025,6 @@ packages: /has-flag/3.0.0: resolution: {integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0=} engines: {node: '>=4'} - dev: true /has-flag/4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} @@ -2387,7 +3052,6 @@ packages: engines: {node: '>= 0.4.0'} dependencies: function-bind: 1.1.1 - dev: true /hash-base/3.1.0: resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} @@ -2409,6 +3073,12 @@ packages: resolution: {integrity: sha512-yR5lWvNz7c85OhVAEAeFhVCc/GV4C30Fjzc/rCP0aCWzc1UUOPUk55dK/qdwTZHBvMZo+eZ2jpk62ndX/xMFlg==} dev: true + /history/5.3.0: + resolution: {integrity: sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==} + dependencies: + '@babel/runtime': 7.17.9 + dev: false + /hmac-drbg/1.0.1: resolution: {integrity: sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=} dependencies: @@ -2417,6 +3087,12 @@ packages: minimalistic-crypto-utils: 1.0.1 dev: true + /hoist-non-react-statics/3.3.2: + resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + dependencies: + react-is: 16.13.1 + dev: false + /htmlnano/2.0.0_svgo@2.8.0: resolution: {integrity: sha512-thKQfhcp2xgtsWNE27A2bliEeqVL5xjAgGn0wajyttvFFsvFWWah1ntV9aEX61gz0T6MBQ5xK/1lXuEumhJTcg==} peerDependencies: @@ -2519,13 +3195,16 @@ packages: engines: {node: '>=6.0.0'} dev: true + /immer/9.0.12: + resolution: {integrity: sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA==} + dev: false + /import-fresh/3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 - dev: true /imurmurhash/0.1.4: resolution: {integrity: sha1-khi5srkoojixPcT7a21XbyMUU+o=} @@ -2555,12 +3234,6 @@ packages: side-channel: 1.0.4 dev: true - /invariant/2.2.4: - resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} - dependencies: - loose-envify: 1.4.0 - dev: false - /is-arguments/1.1.1: resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} engines: {node: '>= 0.4'} @@ -2571,7 +3244,6 @@ packages: /is-arrayish/0.2.1: resolution: {integrity: sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=} - dev: true /is-bigint/1.0.4: resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} @@ -2592,6 +3264,12 @@ packages: engines: {node: '>= 0.4'} dev: true + /is-core-module/2.9.0: + resolution: {integrity: sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==} + dependencies: + has: 1.0.3 + dev: false + /is-date-object/1.0.5: resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} engines: {node: '>= 0.4'} @@ -2770,7 +3448,6 @@ packages: /json-parse-even-better-errors/2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true /json-source-map/0.6.1: resolution: {integrity: sha512-1QoztHPsMQqhDq0hlXY5ZqcEdUzxQEIxgFkKl4WUp2pgShObl+9ovi4kRh2TfvAfxAoHOJ9vIMEqk3k4iex7tg==} @@ -2784,6 +3461,12 @@ packages: minimist: 1.2.5 dev: true + /json5/2.2.1: + resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==} + engines: {node: '>=6'} + hasBin: true + dev: true + /lilconfig/2.0.4: resolution: {integrity: sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==} engines: {node: '>=10'} @@ -2791,7 +3474,6 @@ packages: /lines-and-columns/1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true /lmdb/2.1.7: resolution: {integrity: sha512-i6EFEBBlQ130J4BfJUbYgZFKQDz83xhpM47vzs0BMpXiJ7D4NjecO1Y3X54D341dwkLmTphlIyro5nTkKFXoMQ==} @@ -2980,6 +3662,12 @@ packages: hasBin: true dev: true + /nanoid/3.3.4: + resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: false + /napi-build-utils/1.0.2: resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} dev: false @@ -3023,6 +3711,10 @@ packages: resolution: {integrity: sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==} dev: true + /node-releases/2.0.4: + resolution: {integrity: sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==} + dev: true + /normalize-url/6.1.0: resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} engines: {node: '>=10'} @@ -3178,7 +3870,6 @@ packages: engines: {node: '>=6'} dependencies: callsites: 3.1.0 - dev: true /parse-asn1/5.1.6: resolution: {integrity: sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==} @@ -3198,7 +3889,6 @@ packages: error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 - dev: true /parseqs/0.0.6: resolution: {integrity: sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==} @@ -3231,6 +3921,10 @@ packages: engines: {node: '>=4'} dev: true + /path-parse/1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: false + /path-to-regexp/2.2.1: resolution: {integrity: sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==} dev: true @@ -3238,7 +3932,6 @@ packages: /path-type/4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - dev: true /pbkdf2/3.1.2: resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} @@ -3253,7 +3946,6 @@ packages: /picocolors/1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - dev: true /picomatch/2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} @@ -3661,6 +4353,15 @@ packages: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} dev: true + /postcss/8.4.13: + resolution: {integrity: sha512-jtL6eTBrza5MPzy8oJLFuUscHDXTV5KcLlqAWHl5q5WYRfnNRGSmOZmOZ1T6Gy7A99mOZfqungmZMpMmCVJ8ZA==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.4 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: false + /postcss/8.4.5: resolution: {integrity: sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==} engines: {node: ^10 || ^12 || >=14} @@ -3720,16 +4421,6 @@ packages: engines: {node: '>= 0.6.0'} dev: true - /prop-types-extra/1.1.1_react@17.0.2: - resolution: {integrity: sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==} - peerDependencies: - react: '>=0.14.0' - dependencies: - react: 17.0.2 - react-is: 16.13.1 - warning: 4.0.3 - dev: false - /prop-types/15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} dependencies: @@ -3807,42 +4498,6 @@ packages: strip-json-comments: 2.0.1 dev: false - /react-bootstrap-icons/1.7.2_react@17.0.2: - resolution: {integrity: sha512-FaXk5iHjd6eltoPHUo+onIkcN/xcCEbaEnTeRacibwVlPagEzujFYtUJ0C2+DlvfkWwy5N+b347tSTbtWqBSEg==} - peerDependencies: - react: ^16.8.6 || ^17 - dependencies: - prop-types: 15.8.1 - react: 17.0.2 - dev: false - - /react-bootstrap/2.0.2_react-dom@17.0.2+react@17.0.2: - resolution: {integrity: sha512-QuMqJ+WJmd6dUyOys6OF3nr6T/FjUVAoEMbSjsFrwVufJtvMox0SU1Dvz/cDID+Dl6Rz2RLcJzyqkdl+DEK2Gg==} - peerDependencies: - react: '>=16.14.0' - react-dom: '>=16.14.0' - dependencies: - '@babel/runtime': 7.16.7 - '@restart/context': 2.1.4_react@17.0.2 - '@restart/hooks': 0.3.27_react@17.0.2 - '@restart/ui': 0.2.6_react-dom@17.0.2+react@17.0.2 - '@types/invariant': 2.2.35 - '@types/prop-types': 15.7.4 - '@types/react': 17.0.38 - '@types/react-transition-group': 4.4.4 - '@types/warning': 3.0.0 - classnames: 2.3.1 - dom-helpers: 5.2.1 - invariant: 2.2.4 - prop-types: 15.8.1 - prop-types-extra: 1.1.1_react@17.0.2 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - react-transition-group: 4.4.2_react-dom@17.0.2+react@17.0.2 - uncontrollable: 7.2.1_react@17.0.2 - warning: 4.0.3 - dev: false - /react-dom/17.0.2_react@17.0.2: resolution: {integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==} peerDependencies: @@ -3858,8 +4513,43 @@ packages: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} dev: false - /react-lifecycles-compat/3.0.4: - resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==} + /react-is/17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + dev: false + + /react-is/18.1.0: + resolution: {integrity: sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==} + dev: false + + /react-redux/8.0.1_react-dom@17.0.2+react@17.0.2: + resolution: {integrity: sha512-LMZMsPY4DYdZfLJgd7i79n5Kps5N9XVLCJJeWAaPYTV+Eah2zTuBjTxKtNEbjiyitbq80/eIkm55CYSLqAub3w==} + peerDependencies: + '@types/react': ^16.8 || ^17.0 || ^18.0 + '@types/react-dom': ^16.8 || ^17.0 || ^18.0 + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + react-native: '>=0.59' + redux: ^4 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + react-dom: + optional: true + react-native: + optional: true + redux: + optional: true + dependencies: + '@babel/runtime': 7.17.9 + '@types/hoist-non-react-statics': 3.3.1 + '@types/use-sync-external-store': 0.0.3 + hoist-non-react-statics: 3.3.2 + react: 17.0.2 + react-dom: 17.0.2_react@17.0.2 + react-is: 18.1.0 + use-sync-external-store: 1.1.0_react@17.0.2 dev: false /react-refresh/0.9.0: @@ -3867,6 +4557,27 @@ packages: engines: {node: '>=0.10.0'} dev: true + /react-router-dom/6.3.0_react-dom@17.0.2+react@17.0.2: + resolution: {integrity: sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==} + peerDependencies: + react: '>=16.8' + react-dom: '>=16.8' + dependencies: + history: 5.3.0 + react: 17.0.2 + react-dom: 17.0.2_react@17.0.2 + react-router: 6.3.0_react@17.0.2 + dev: false + + /react-router/6.3.0_react@17.0.2: + resolution: {integrity: sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==} + peerDependencies: + react: '>=16.8' + dependencies: + history: 5.3.0 + react: 17.0.2 + dev: false + /react-transition-group/4.4.2_react-dom@17.0.2+react@17.0.2: resolution: {integrity: sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==} peerDependencies: @@ -3908,6 +4619,20 @@ packages: string_decoder: 1.3.0 util-deprecate: 1.0.2 + /redux-thunk/2.4.1_redux@4.2.0: + resolution: {integrity: sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==} + peerDependencies: + redux: ^4 + dependencies: + redux: 4.2.0 + dev: false + + /redux/4.2.0: + resolution: {integrity: sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==} + dependencies: + '@babel/runtime': 7.17.9 + dev: false + /regenerator-runtime/0.13.9: resolution: {integrity: sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==} @@ -3915,10 +4640,22 @@ packages: resolution: {integrity: sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=} dev: true + /reselect/4.1.5: + resolution: {integrity: sha512-uVdlz8J7OO+ASpBYoz1Zypgx0KasCY20H+N8JD13oUMtPvSHQuscrHop4KbXrbsBcdB9Ds7lVK7eRkBIfO43vQ==} + dev: false + /resolve-from/4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - dev: true + + /resolve/1.22.0: + resolution: {integrity: sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==} + hasBin: true + dependencies: + is-core-module: 2.9.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: false /restore-cursor/3.1.0: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} @@ -3947,6 +4684,14 @@ packages: inherits: 2.0.4 dev: true + /rollup/2.72.0: + resolution: {integrity: sha512-KqtR2YcO35/KKijg4nx4STO3569aqCUeGRkKWnJ6r+AvBBrVY9L4pmf4NHVrQr4mTOq6msbohflxr2kpihhaOA==} + engines: {node: '>=10.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.2 + dev: false + /run-parallel/1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: @@ -4127,7 +4872,6 @@ packages: /source-map-js/1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} - dev: true /source-map-support/0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} @@ -4139,7 +4883,6 @@ packages: /source-map/0.5.7: resolution: {integrity: sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=} engines: {node: '>=0.10.0'} - dev: true /source-map/0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} @@ -4262,12 +5005,15 @@ packages: postcss-selector-parser: 6.0.9 dev: true + /stylis/4.0.13: + resolution: {integrity: sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag==} + dev: false + /supports-color/5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} dependencies: has-flag: 3.0.0 - dev: true /supports-color/7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} @@ -4284,6 +5030,11 @@ packages: supports-color: 7.2.0 dev: true + /supports-preserve-symlinks-flag/1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: false + /svgo/2.8.0: resolution: {integrity: sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==} engines: {node: '>=10.13.0'} @@ -4360,7 +5111,6 @@ packages: /to-fast-properties/2.0.0: resolution: {integrity: sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=} engines: {node: '>=4'} - dev: true /to-regex-range/5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} @@ -4408,18 +5158,6 @@ packages: which-boxed-primitive: 1.0.2 dev: true - /uncontrollable/7.2.1_react@17.0.2: - resolution: {integrity: sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==} - peerDependencies: - react: '>=15.0.0' - dependencies: - '@babel/runtime': 7.16.7 - '@types/react': 17.0.38 - invariant: 2.2.4 - react: 17.0.2 - react-lifecycles-compat: 3.0.4 - dev: false - /unpipe/1.0.0: resolution: {integrity: sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=} engines: {node: '>= 0.8'} @@ -4432,6 +5170,14 @@ packages: querystring: 0.2.0 dev: true + /use-sync-external-store/1.1.0_react@17.0.2: + resolution: {integrity: sha512-SEnieB2FPKEVne66NpXPd1Np4R1lTNKfjuy3XdIoPQKYBAFdzbzSZlSn1KJZUiihQLQC5Znot4SBz1EOTBwQAQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + react: 17.0.2 + dev: false + /util-deprecate/1.0.2: resolution: {integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=} @@ -4470,16 +5216,34 @@ packages: engines: {node: '>= 0.8'} dev: false + /vite/2.9.8: + resolution: {integrity: sha512-zsBGwn5UT3YS0NLSJ7hnR54+vUKfgzMUh/Z9CxF1YKEBVIe213+63jrFLmZphgGI5zXwQCSmqIdbPuE8NJywPw==} + engines: {node: '>=12.2.0'} + hasBin: true + peerDependencies: + less: '*' + sass: '*' + stylus: '*' + peerDependenciesMeta: + less: + optional: true + sass: + optional: true + stylus: + optional: true + dependencies: + esbuild: 0.14.38 + postcss: 8.4.13 + resolve: 1.22.0 + rollup: 2.72.0 + optionalDependencies: + fsevents: 2.3.2 + dev: false + /vm-browserify/1.1.2: resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==} dev: true - /warning/4.0.3: - resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} - dependencies: - loose-envify: 1.4.0 - dev: false - /wcwidth/1.0.1: resolution: {integrity: sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=} dependencies: @@ -4583,7 +5347,6 @@ packages: /yaml/1.10.2: resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} engines: {node: '>= 6'} - dev: true /yeast/0.1.2: resolution: {integrity: sha1-AI4G2AlDIMNy28L47XagymyKxBk=} diff --git a/server/src/core/downloader.ts b/server/src/core/downloader.ts index 33f5462..915d708 100644 --- a/server/src/core/downloader.ts +++ b/server/src/core/downloader.ts @@ -46,7 +46,6 @@ export async function download(socket: Socket, payload: IPayload) { const p = new Process(url, params, settings); p.start().then(downloader => { - pool.add(p) let infoLock = true; let pid = downloader.getPid(); @@ -91,7 +90,7 @@ export async function download(socket: Socket, payload: IPayload) { * @param {Socket} socket current connection socket * @returns */ -export async function retriveDownload(socket: Socket) { +export async function retrieveDownload(socket: Socket) { // it's a cold restart: the server has just been started with pending // downloads, so fetch them from the database and resume. if (coldRestart) { @@ -110,7 +109,9 @@ export async function retriveDownload(socket: Socket) { // it's an hot-reload the server it's running and the frontend ask for // the pending job: retrieve them from the "in-memory database" (ProcessPool) - log.info('dl', `Retrieving ${pool.size()} jobs from pool`) + const _poolSize = pool.size() + log.info('dl', `Retrieving ${_poolSize} jobs from pool`) + socket.emit('pending-jobs', _poolSize) const it = pool.iterator(); const tempWorkQueue = new Array(); @@ -169,6 +170,13 @@ export function abortAllDownloads(socket: Socket) { }); } +/** + * Get pool current size + */ +export function getQueueSize(): number { + return pool.size(); +} + /** * @private Formats the yt-dlp stdout to a frontend-readable format * @param {string} stdout stdout as string diff --git a/server/src/main.ts b/server/src/main.ts index e127b0b..0ec8244 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -2,8 +2,8 @@ import { logger, splash } from './utils/logger'; import { join } from 'path'; import { Server } from 'socket.io'; import { ytdlpUpdater } from './utils/updater'; -import { download, abortDownload, retriveDownload, abortAllDownloads } from './core/downloader'; -import { retrieveAll, init } from './db/db'; +import { download, abortDownload, retrieveDownload, abortAllDownloads } from './core/downloader'; +import { init } from './db/db'; import { getFreeDiskSpace } from './utils/procUtils'; import Logger from './utils/BetterLogger'; import Jean from './core/HTTPServer'; @@ -36,11 +36,8 @@ io.on('connection', socket => { socket.on('update-bin', () => { ytdlpUpdater(socket) }) - socket.on('fetch-jobs', () => { - socket.emit('pending-jobs', retrieveAll()) - }) socket.on('retrieve-jobs', () => { - retriveDownload(socket) + retrieveDownload(socket) }) socket.on('disk-space', () => { getFreeDiskSpace(socket)