diff --git a/items/frontend/package.json b/items/frontend/package.json
index 70df6b5..32d3d53 100644
--- a/items/frontend/package.json
+++ b/items/frontend/package.json
@@ -13,8 +13,9 @@
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"cross-env": "^7.0.3",
- "cypress": "^8.6.0",
- "start-server-and-test": "^1.14.0"
+ "cypress": "9.0.0",
+ "start-server-and-test": "^1.14.0",
+ "typescript": "^4.1.2"
},
"dependencies": {
"@emotion/react": "^11.4.1",
@@ -22,11 +23,12 @@
"@mui/icons-material": "^5.0.3",
"@mui/material": "^5.0.3",
"@mui/styles": "^5.0.1",
+ "history": "5",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-json-view": "^1.21.3",
+ "react-router-dom": "6",
"react-scripts": "4.0.3",
- "typescript": "^4.1.2",
"web-vitals": "^1.0.1",
"zustand": "^3.5.13"
},
@@ -59,8 +61,13 @@
]
},
"nyc": {
- "include":["src/**/*.ts", "src/**/*.tsx"],
- "exclude": ["src/reportWebVitals.ts"],
+ "include": [
+ "src/**/*.ts",
+ "src/**/*.tsx"
+ ],
+ "exclude": [
+ "src/reportWebVitals.ts"
+ ],
"excludeAfterRemap": true
}
}
diff --git a/items/frontend/src/index.tsx b/items/frontend/src/index.tsx
index 7998135..6031b20 100644
--- a/items/frontend/src/index.tsx
+++ b/items/frontend/src/index.tsx
@@ -4,13 +4,13 @@ import App from './App';
import reportWebVitals from './reportWebVitals';
ReactDOM.render(
-
-
- ,
- document.getElementById('root')
+
+
+ ,
+ document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
-reportWebVitals();
+reportWebVitals();
\ No newline at end of file
diff --git a/items/frontend/src/pages/InteractiveArea.tsx b/items/frontend/src/pages/InteractiveArea.tsx
new file mode 100644
index 0000000..34a79d7
--- /dev/null
+++ b/items/frontend/src/pages/InteractiveArea.tsx
@@ -0,0 +1,26 @@
+import {Box} from '@mui/material'
+import {NavigationBreadcrumb} from './mainPageComponents/NavigationBreadcrumb'
+import {SearchArea} from './mainPageComponents/SearchArea'
+import {makeStyles} from "@mui/styles";
+import React from "react";
+
+const useStyles = makeStyles(() => ({
+ searchContainer: {
+ display: 'flex',
+ flexDirection: 'row',
+ flexGrow: 1,
+ padding: '2vh 2vw 1vh 2vw'
+ }
+}))
+
+export const InteractiveArea = () => {
+ const classes = useStyles();
+ return (
+ <>
+
+
+
+
+ >
+ )
+}
diff --git a/items/frontend/src/pages/MainPage.tsx b/items/frontend/src/pages/MainPage.tsx
index a5c3b33..4d92486 100644
--- a/items/frontend/src/pages/MainPage.tsx
+++ b/items/frontend/src/pages/MainPage.tsx
@@ -1,11 +1,13 @@
-import {Box, Theme} from '@mui/material'
+import {Box} from '@mui/material'
import {Footer} from '../components/Footer'
import {Header} from '../components/Header'
-import {NavigationBreadcrumb} from './mainPageComponents/NavigationBreadcrumb'
-import {SearchArea} from './mainPageComponents/SearchArea'
import {makeStyles} from "@mui/styles";
+import {BrowserRouter, Navigate, Route, Routes} from "react-router-dom";
+import React from "react";
+import {InteractiveArea} from "./InteractiveArea";
+import {PageNotFound} from "./PageNotFound";
-const useStyles = makeStyles((theme: Theme) => ({
+const useStyles = makeStyles(() => ({
container: {
background: 'background.default',
display: 'flex',
@@ -13,12 +15,6 @@ const useStyles = makeStyles((theme: Theme) => ({
flexGrow: 1,
height: '100vh',
maxheight: '100vh',
- },
- searchContainer: {
- display: 'flex',
- flexDirection: 'row',
- flexGrow: 1,
- padding: '2vh 2vw 1vh 2vw'
}
}))
@@ -28,10 +24,15 @@ export const MainPage = () => {
<>
-
-
-
-
+
+
+ }>
+ }/>
+
+ }/>
+ }/>
+
+
>
diff --git a/items/frontend/src/pages/PageNotFound.tsx b/items/frontend/src/pages/PageNotFound.tsx
new file mode 100644
index 0000000..5e6f52d
--- /dev/null
+++ b/items/frontend/src/pages/PageNotFound.tsx
@@ -0,0 +1,44 @@
+import {Box, Theme, Typography} from '@mui/material'
+import {NavigationBreadcrumb} from './mainPageComponents/NavigationBreadcrumb'
+import {makeStyles} from "@mui/styles";
+import React from "react";
+
+const useStyles = makeStyles((theme: Theme) => ({
+ searchContainer: {
+ display: 'flex',
+ flexDirection: 'row',
+ flexGrow: 1,
+ padding: '2vh 2vw 1vh 2vw'
+ },
+ notFoundAreaHolder: {
+ display: 'flex',
+ flexGrow: 1,
+ flexDirection: 'column',
+ background: theme.palette.background.paper,
+ padding: '2vh 2vw 2vh 2vw',
+ },
+ notFoundContainer: {
+ display: 'flex',
+ flexGrow: 1,
+ flexDirection: 'column',
+ width: "100%",
+ alignItems: "center",
+ paddingTop: "10vh"
+ },
+}))
+
+export const PageNotFound = () => {
+ const classes = useStyles();
+ return (
+ <>
+
+
+
+
+ This page does not exist !
+
+
+
+ >
+ )
+}
diff --git a/items/frontend/src/pages/mainPageComponents/SearchArea.tsx b/items/frontend/src/pages/mainPageComponents/SearchArea.tsx
index d1711ff..23d4196 100644
--- a/items/frontend/src/pages/mainPageComponents/SearchArea.tsx
+++ b/items/frontend/src/pages/mainPageComponents/SearchArea.tsx
@@ -1,195 +1,202 @@
-import { SyntheticEvent, useCallback, useEffect, useState } from 'react'
-import {
- Autocomplete,
- Box,
- CircularProgress,
- Theme,
- Typography,
-} from '@mui/material'
-import { makeStyles } from '@mui/styles'
+import {SyntheticEvent, useCallback, useEffect, useState} from 'react'
+import {Autocomplete, Box, CircularProgress, Theme, Typography,} from '@mui/material'
+import {makeStyles} from '@mui/styles'
import TextField from '@mui/material/TextField'
import ReactJson from 'react-json-view'
-import {
- getItem,
- getItemHierarchy,
- searchItem,
-} from '../../dataaccess/ItemBackend'
-import { ItemOption } from '../../dto/ItemOption'
-import { useGlobalState } from '../../state/GlobalState'
+import {getItem, getItemHierarchy, searchItem,} from '../../dataaccess/ItemBackend'
+import {ItemOption} from '../../dto/ItemOption'
+import {useGlobalState} from '../../state/GlobalState'
+import {useNavigate, useParams} from "react-router-dom";
interface IItemOption {
- id?: string
- name?: string
- shortName?: string
+ id?: string
+ name?: string
+ shortName?: string
}
const useStyles = makeStyles((theme: Theme) => ({
- searchAreaHolder: {
- display: 'flex',
- flexGrow: 1,
- flexDirection: 'column',
- background: theme.palette.background.paper,
- padding: '2vh 2vw 2vh 2vw',
- },
- jsonHolder: {
- display: 'flex',
- flexGrow: 1,
- alignItems: 'center',
- flexDirection: 'column',
- background: theme.palette.background.paper,
- maxHeight: '80vh',
- },
- autocomplete: {},
+ searchAreaHolder: {
+ display: 'flex',
+ flexGrow: 1,
+ flexDirection: 'column',
+ background: theme.palette.background.paper,
+ padding: '2vh 2vw 2vh 2vw',
+ },
+ jsonHolder: {
+ display: 'flex',
+ flexGrow: 1,
+ alignItems: 'center',
+ flexDirection: 'column',
+ background: theme.palette.background.paper,
+ maxHeight: '80vh',
+ },
+ autocomplete: {},
}))
export const SearchArea = () => {
- const classes = useStyles()
- const preferedLocale = useGlobalState((state) => state.preferedLocale)
- const preferedJsonViewerTheme = useGlobalState(
- useCallback((state) => state.preferedJsonViewerTheme, []),
- )
- const [searchInputState, setSearchInput] = useGlobalState((state) => [
- state.searchInput,
- state.setSearchInput,
- ])
- const [setHierarchy, initHierarchy] = useGlobalState((state) => [state.setHierarchy, state.initHierarchy])
- const [selectedItem, setSelectedItem] = useGlobalState((state) => [
- state.selectedItem,
- state.setSelectedItem,
- ])
- const [selectOptions, setSelecteOptions] = useState([])
- const [isbusy, setIsBusy] = useState(false)
- const searchThreshold = 3
-
- const handleNameInput = async (input: string) => {
- const searchResults = await searchItem(input, preferedLocale)
- const options = searchResults?.map((res) => ({
- id: res.item._id,
- name: res.locale.Name ? res.locale.Name : res.item._name,
- shortName: JSON.stringify(res.locale.ShortName)
- }))
- setSelecteOptions(options ? options : [])
- }
-
- const handleIDInput = useCallback(async (input: string) => {
- const itemJson = await getItem(input, preferedLocale)
- if (!itemJson) {
- setSelectedItem(undefined)
- setSearchInput('')
- return;
- }
-
- setSelectedItem(itemJson)
- const itemObj = {
- id: itemJson.item._id,
- name: itemJson.locale.Name ? itemJson.locale.Name : itemJson.item._name,
- shortName: itemJson.locale.ShortName
- }
- setSelecteOptions([itemObj])
- setSearchInput(itemObj.name)
-
- // Update hierachy
- const itemHierarchy = await getItemHierarchy(
- itemJson.item,
- preferedLocale,
+ const classes = useStyles()
+ const params = useParams();
+ const navigate = useNavigate();
+ const preferedLocale = useGlobalState((state) => state.preferedLocale)
+ const preferedJsonViewerTheme = useGlobalState(
+ useCallback((state) => state.preferedJsonViewerTheme, []),
)
- setHierarchy(itemHierarchy ? itemHierarchy : {})
- // eslint-disable-next-line
- }, []) // Need to only be created on startup
+ const [searchInputState, setSearchInput] = useGlobalState((state) => [
+ state.searchInput,
+ state.setSearchInput,
+ ])
+ const [setHierarchy, initHierarchy] = useGlobalState((state) => [state.setHierarchy, state.initHierarchy])
+ const [selectedItem, setSelectedItem] = useGlobalState((state) => [
+ state.selectedItem,
+ state.setSelectedItem,
+ ])
+ const [selectOptions, setSelecteOptions] = useState([])
+ const [isbusy, setIsBusy] = useState(false)
+ const searchThreshold = 3
- useEffect(() => initHierarchy(), [initHierarchy])
+ const handleNameInput = useCallback(async (input: string) => {
+ const searchResults = await searchItem(input, preferedLocale)
+ const options = searchResults?.map((res) => ({
+ id: res.item._id,
+ name: res.locale.Name ? res.locale.Name : res.item._name,
+ shortName: JSON.stringify(res.locale.ShortName)
+ }))
+ setSelecteOptions(options ? options : [])
+ }, [preferedLocale])
- useEffect(() => {
- if (searchInputState && searchInputState.match(/([a-z0-9]{24})/)) {
- handleIDInput(searchInputState)
- }
- }, [handleIDInput, searchInputState])
+ const handleIDInput = useCallback(async (input: string) => {
+ const itemJson = await getItem(input, preferedLocale)
+ if (!itemJson) {
+ setSelectedItem(undefined)
+ setSearchInput('')
+ return;
+ }
- const handleInput = async (input: string) => {
- if (!input || input.length < searchThreshold || isbusy) {
- setSelectedItem(undefined)
- setSelecteOptions([])
- setIsBusy(false)
- return
- }
- setIsBusy(true)
+ setSelectedItem(itemJson)
+ const itemObj = {
+ id: itemJson.item._id,
+ name: itemJson.locale.Name ? itemJson.locale.Name : itemJson.item._name,
+ shortName: itemJson.locale.ShortName
+ }
+ setSelecteOptions([itemObj])
+ setSearchInput(itemObj.name)
- if (input.match(/([a-z0-9]{24})/)) await handleIDInput(input)
- else await handleNameInput(input)
+ // Update hierachy
+ const itemHierarchy = await getItemHierarchy(
+ itemJson.item,
+ preferedLocale,
+ )
+ setHierarchy(itemHierarchy ? itemHierarchy : {})
+ // eslint-disable-next-line
+ }, []) // Need to only be created on startup
- setIsBusy(false)
- }
+ useEffect(() => initHierarchy(), [initHierarchy])
- const formatDisplayItems = () => {
- // If loading
- if (isbusy) return
+ useEffect(()=>{
+ if (selectedItem){
+ navigate(`/search/${selectedItem.item._id}`)
+ }
+ },[selectedItem, navigate])
- // If finished loading
- if (selectedItem){
- return (
-
- )
- }
- else return No data to display
- }
+ useEffect(() => {
+ if (searchInputState && searchInputState.match(/([a-z0-9]{24})/)) {
+ handleIDInput(searchInputState)
+ }
+ }, [handleIDInput, searchInputState])
- const findOptionValue = (option: ItemOption, value: ItemOption): boolean => {
- return option.name?.toLocaleLowerCase() === value.name?.toLocaleLowerCase()
- || option.id?.toLocaleLowerCase() === value.id?.toLocaleLowerCase()
- || option.shortName?.toLocaleLowerCase() === value.shortName?.toLocaleLowerCase()
- }
+ const handleInput = useCallback(async (input: string) => {
+ if (!input || input.length < searchThreshold || isbusy) {
+ setSelectedItem(undefined)
+ setSelecteOptions([])
+ setIsBusy(false)
+ return
+ }
+ setIsBusy(true)
- return (
-
- ({name: elt.name, shortName: elt.shortName, id: elt.id}))}
- getOptionLabel={(option)=> option.name ? option.name : option.id}
- isOptionEqualToValue={(option, value) => findOptionValue(option, value)}
- open={!isbusy && searchInputState.length >= searchThreshold && (searchInputState !== selectedItem?.locale.Name && searchInputState !== selectedItem?.item._name)}
- className={classes.autocomplete}
- inputValue={searchInputState ? searchInputState : ''}
- onInputChange={async (evt: SyntheticEvent, newValue: string) => {
- if (!evt) return
- setSelectedItem(undefined)
- setSearchInput(newValue)
- await handleInput(newValue.trim())
- }}
- value={(()=>{
- const selectedOption = selectOptions.find(elt => elt.id === searchInputState || elt.name === searchInputState);
- return selectedOption ? selectedOption : null;
- })()}
- onChange={async (event: SyntheticEvent, newValue: IItemOption | null) => {
- if (newValue) {
- const selectedOption = selectOptions.find(
- (elt) => elt.name === newValue.name,
+ if (input.match(/([a-z0-9]{24})/)) await handleIDInput(input)
+ else await handleNameInput(input)
+
+ setIsBusy(false)
+ }, [handleIDInput, handleNameInput, isbusy, setSelectedItem])
+
+ useEffect(() => {
+ if (!searchInputState && params.id) {
+ const newId = params.id.trim();
+ console.log(newId);
+ setSearchInput(newId);
+ (async () => await handleInput(newId))();
+ }
+ }, [params, searchInputState, setSearchInput, handleInput, navigate])
+
+ const formatDisplayItems = () => {
+ // If loading
+ if (isbusy) return
+
+ // If finished loading
+ if (selectedItem) {
+ return (
+
)
- if (selectedOption) await handleIDInput(selectedOption.id)
- }
- }}
- renderInput={(params) =>(
-
- )}
- renderOption={(props, option, state) => (
- {option.name}
- )}
- filterOptions={(options, state) => options.filter(elt =>{
- return (elt.name?.toLocaleLowerCase().includes(state.inputValue.toLocaleLowerCase())
- || elt.id?.toLocaleLowerCase().includes(state.inputValue.toLocaleLowerCase())
- || elt.shortName?.toLocaleLowerCase().includes(state.inputValue.toLocaleLowerCase()))
- })}
- filterSelectedOptions
- />
- {formatDisplayItems()}
-
- )
+ } else return No data to display
+ }
+
+ const findOptionValue = (option: ItemOption, value: ItemOption): boolean => {
+ return option.name?.toLocaleLowerCase() === value.name?.toLocaleLowerCase()
+ || option.id?.toLocaleLowerCase() === value.id?.toLocaleLowerCase()
+ || option.shortName?.toLocaleLowerCase() === value.shortName?.toLocaleLowerCase()
+ }
+
+ return (
+
+ ({name: elt.name, shortName: elt.shortName, id: elt.id}))}
+ getOptionLabel={(option) => option.name ? option.name : option.id}
+ isOptionEqualToValue={(option, value) => findOptionValue(option, value)}
+ open={!isbusy && searchInputState.length >= searchThreshold && (searchInputState !== selectedItem?.locale.Name && searchInputState !== selectedItem?.item._name)}
+ className={classes.autocomplete}
+ inputValue={searchInputState ? searchInputState : ''}
+ onInputChange={async (evt: SyntheticEvent, newValue: string) => {
+ if (!evt) return
+ setSelectedItem(undefined)
+ setSearchInput(newValue)
+ await handleInput(newValue.trim())
+ }}
+ value={(() => {
+ const selectedOption = selectOptions.find(elt => elt.id === searchInputState || elt.name === searchInputState);
+ return selectedOption ? selectedOption : null;
+ })()}
+ onChange={async (event: SyntheticEvent, newValue: IItemOption | null) => {
+ if (newValue) {
+ const selectedOption = selectOptions.find(
+ (elt) => elt.name === newValue.name,
+ )
+ if (selectedOption) await handleIDInput(selectedOption.id)
+ }
+ }}
+ renderInput={(params) => (
+
+ )}
+ renderOption={(props, option ) => (
+ {option.name}
+ )}
+ filterOptions={(options, state) => options.filter(elt => {
+ return (elt.name?.toLocaleLowerCase().includes(state.inputValue.toLocaleLowerCase())
+ || elt.id?.toLocaleLowerCase().includes(state.inputValue.toLocaleLowerCase())
+ || elt.shortName?.toLocaleLowerCase().includes(state.inputValue.toLocaleLowerCase()))
+ })}
+ filterSelectedOptions
+ />
+ {formatDisplayItems()}
+
+ )
}
diff --git a/items/frontend/yarn.lock b/items/frontend/yarn.lock
index b4b41b4..8ae89ba 100644
--- a/items/frontend/yarn.lock
+++ b/items/frontend/yarn.lock
@@ -1282,6 +1282,13 @@
dependencies:
regenerator-runtime "^0.13.4"
+"@babel/runtime@^7.7.6":
+ version "7.16.3"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.3.tgz#b86f0db02a04187a3c17caa77de69840165d42d5"
+ integrity sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ==
+ dependencies:
+ regenerator-runtime "^0.13.4"
+
"@babel/template@^7.10.4", "@babel/template@^7.15.4", "@babel/template@^7.3.3", "@babel/template@^7.4.4":
version "7.15.4"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.15.4.tgz#51898d35dcf3faa670c4ee6afcfd517ee139f194"
@@ -1385,10 +1392,10 @@
debug "4.2.0"
find-yarn-workspace-root "^2.0.0"
-"@cypress/request@^2.88.6":
- version "2.88.6"
- resolved "https://registry.yarnpkg.com/@cypress/request/-/request-2.88.6.tgz#a970dd675befc6bdf8a8921576c01f51cc5798e9"
- integrity sha512-z0UxBE/+qaESAHY9p9sM2h8Y4XqtsbDCt0/DPOrqA/RZgKi4PkxdpXyK4wCCnSk1xHqWHZZAE+gV6aDAR6+caQ==
+"@cypress/request@^2.88.7":
+ version "2.88.7"
+ resolved "https://registry.yarnpkg.com/@cypress/request/-/request-2.88.7.tgz#386d960ab845a96953723348088525d5a75aaac4"
+ integrity sha512-FTULIP2rnDJvZDT9t6B4nSfYR40ue19tVmv3wUcY05R9/FPCoMl1nAPJkzWzBCo7ltVn5ThQTbxiMoGBN7k0ig==
dependencies:
aws-sign2 "~0.7.0"
aws4 "^1.8.0"
@@ -4876,12 +4883,12 @@ cyclist@^1.0.1:
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=
-cypress@^8.6.0:
- version "8.6.0"
- resolved "https://registry.yarnpkg.com/cypress/-/cypress-8.6.0.tgz#8d02fa58878b37cfc45bbfce393aa974fa8a8e22"
- integrity sha512-F7qEK/6Go5FsqTueR+0wEw2vOVKNgk5847Mys8vsWkzPoEKdxs+7N9Y1dit+zhaZCLtMPyrMwjfA53ZFy+lSww==
+cypress@9.0.0:
+ version "9.0.0"
+ resolved "https://registry.yarnpkg.com/cypress/-/cypress-9.0.0.tgz#8c496f7f350e611604cc2f77b663fb81d0c235d2"
+ integrity sha512-/93SWBZTw7BjFZ+I9S8SqkFYZx7VhedDjTtRBmXO0VzTeDbmxgK/snMJm/VFjrqk/caWbI+XY4Qr80myDMQvYg==
dependencies:
- "@cypress/request" "^2.88.6"
+ "@cypress/request" "^2.88.7"
"@cypress/xvfb" "^1.2.4"
"@types/node" "^14.14.31"
"@types/sinonjs__fake-timers" "^6.0.2"
@@ -4916,7 +4923,6 @@ cypress@^8.6.0:
ospath "^1.2.2"
pretty-bytes "^5.6.0"
proxy-from-env "1.0.0"
- ramda "~0.27.1"
request-progress "^3.0.0"
supports-color "^8.1.1"
tmp "~0.2.1"
@@ -6802,6 +6808,13 @@ hex-color-regex@^1.1.0:
resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e"
integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==
+history@5, history@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/history/-/history-5.1.0.tgz#2e93c09c064194d38d52ed62afd0afc9d9b01ece"
+ integrity sha512-zPuQgPacm2vH2xdORvGGz1wQMuHSIB56yNAy5FnLuwOwgSYyPKptJtcMm6Ev+hRGeS+GzhbmRacHzvlESbFwDg==
+ dependencies:
+ "@babel/runtime" "^7.7.6"
+
hmac-drbg@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
@@ -10838,11 +10851,6 @@ raf@^3.4.1:
dependencies:
performance-now "^2.1.0"
-ramda@~0.27.1:
- version "0.27.1"
- resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.1.tgz#66fc2df3ef873874ffc2da6aa8984658abacf5c9"
- integrity sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw==
-
randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
@@ -10969,6 +10977,21 @@ react-refresh@^0.8.3:
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==
+react-router-dom@6:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.0.2.tgz#860cefa697b9d4965eced3f91e82cdbc5995f3ad"
+ integrity sha512-cOpJ4B6raFutr0EG8O/M2fEoyQmwvZWomf1c6W2YXBZuFBx8oTk/zqjXghwScyhfrtnt0lANXV2182NQblRxFA==
+ dependencies:
+ history "^5.1.0"
+ react-router "6.0.2"
+
+react-router@6.0.2:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.0.2.tgz#bd2b0fa84fd1d152671e9f654d9c0b1f5a7c86da"
+ integrity sha512-8/Wm3Ed8t7TuedXjAvV39+c8j0vwrI5qVsYqjFr5WkJjsJpEvNSoLRUbtqSEYzqaTUj1IV+sbPJxvO+accvU0Q==
+ dependencies:
+ history "^5.1.0"
+
react-scripts@4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-4.0.3.tgz#b1cafed7c3fa603e7628ba0f187787964cb5d345"