From 432bddfaed569aca29eac236eda853e33a6b7112 Mon Sep 17 00:00:00 2001 From: AMW - Game & Entertainment Date: Sat, 27 Aug 2022 11:01:23 +0200 Subject: [PATCH 01/11] fix: Fixed paths to use alias & renamed component readability --- src/components/profile/Content.tsx | 18 ------------------ src/pages/profile/index.tsx | 4 ++-- src/plugins/routing.tsx | 8 ++++---- src/services/QueryClient.ts | 2 +- src/utils/readable.ts | 2 +- 5 files changed, 8 insertions(+), 26 deletions(-) delete mode 100644 src/components/profile/Content.tsx diff --git a/src/components/profile/Content.tsx b/src/components/profile/Content.tsx deleted file mode 100644 index 75d4537..0000000 --- a/src/components/profile/Content.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { Descriptions } from 'antd'; -import { MultiCategoryDetails } from '@api/endpoints/profile'; -import { toCapitalize } from '@utils/text'; - -const ProfileContent = ({ data = {} as Partial, column = 2 }) => ( - - { - Object.keys(data) - .map((key: string, index: number) => - - {data[key as keyof MultiCategoryDetails] as string} - - ) - } - -); - -export default ProfileContent; \ No newline at end of file diff --git a/src/pages/profile/index.tsx b/src/pages/profile/index.tsx index d27a182..8d88d50 100644 --- a/src/pages/profile/index.tsx +++ b/src/pages/profile/index.tsx @@ -4,9 +4,9 @@ import { PageHeader, Result, Skeleton } from 'antd'; import { MultiCategoryDetails } from '@api/endpoints/profile'; import { SearchCategory } from '@api/endpoints/search'; import { useProfile } from '@hooks/profile/useProfile'; -import ProfileContent from '@components/profile/Content' +import ProfileContent from '@components/profile/ProfileContent' import RelatedProfileTabs from "@components/profile/RelatedProfileTabs"; -import GeneralError from "../errors/general"; +import GeneralError from "@pages/errors/general"; import { categoryToReadable } from "@utils/readable"; const viewableCategories = Object.values(SearchCategory).filter((currentCategory) => currentCategory !== SearchCategory.ALL); diff --git a/src/plugins/routing.tsx b/src/plugins/routing.tsx index c7eb244..69bad72 100644 --- a/src/plugins/routing.tsx +++ b/src/plugins/routing.tsx @@ -1,8 +1,8 @@ import type { RouteObject } from "react-router-dom"; -import NoMatch from '../pages/errors/404' -import MainSearch from '../pages/search' -import Profile from '../pages/profile' -import SearchList from '../components/search/SearchList' +import NoMatch from '@pages/errors/404' +import MainSearch from '@pages/search' +import Profile from '@pages/profile' +import SearchList from '@components/search/SearchList' const routes: RouteObject[] = [ { diff --git a/src/services/QueryClient.ts b/src/services/QueryClient.ts index b1136cb..a11674a 100644 --- a/src/services/QueryClient.ts +++ b/src/services/QueryClient.ts @@ -1,6 +1,6 @@ import { QueryClient } from '@tanstack/react-query'; -import { isApiError }from '../utils/api' +import { isApiError }from '@utils/api' const queryClient = new QueryClient({ defaultOptions: { diff --git a/src/utils/readable.ts b/src/utils/readable.ts index d5a37f9..aad8a81 100644 --- a/src/utils/readable.ts +++ b/src/utils/readable.ts @@ -1,4 +1,4 @@ -import { SearchCategory } from "../api/endpoints/search" +import { SearchCategory } from "@api/endpoints/search" export const categoryToReadable = (category: string) => { switch (category) { From d320532834b9887b810555f84345cd1e42ca001a Mon Sep 17 00:00:00 2001 From: AMW - Game & Entertainment Date: Sat, 27 Aug 2022 11:01:56 +0200 Subject: [PATCH 02/11] feat: Split list item into seperate component and using useCallback for performance --- src/components/profile/ProfileContent.tsx | 18 ++++++++++++++++ src/components/search/SearchList.tsx | 19 ++++++----------- src/components/search/SearchListItem.tsx | 25 +++++++++++++++++++++++ 3 files changed, 49 insertions(+), 13 deletions(-) create mode 100644 src/components/profile/ProfileContent.tsx create mode 100644 src/components/search/SearchListItem.tsx diff --git a/src/components/profile/ProfileContent.tsx b/src/components/profile/ProfileContent.tsx new file mode 100644 index 0000000..75d4537 --- /dev/null +++ b/src/components/profile/ProfileContent.tsx @@ -0,0 +1,18 @@ +import { Descriptions } from 'antd'; +import { MultiCategoryDetails } from '@api/endpoints/profile'; +import { toCapitalize } from '@utils/text'; + +const ProfileContent = ({ data = {} as Partial, column = 2 }) => ( + + { + Object.keys(data) + .map((key: string, index: number) => + + {data[key as keyof MultiCategoryDetails] as string} + + ) + } + +); + +export default ProfileContent; \ No newline at end of file diff --git a/src/components/search/SearchList.tsx b/src/components/search/SearchList.tsx index 799ae1b..d4c5926 100644 --- a/src/components/search/SearchList.tsx +++ b/src/components/search/SearchList.tsx @@ -1,6 +1,6 @@ import React, { useCallback } from 'react'; -import { Link, useNavigate } from "react-router-dom"; -import { Skeleton, List } from 'antd'; +import { useNavigate } from "react-router-dom"; +import { List } from 'antd'; import { useSearch } from '@hooks/search/useSearch' import { MultiCategoryDetails } from '@api/endpoints/profile'; import { SearchCategory } from '@api/endpoints/search'; @@ -8,6 +8,7 @@ import useSearchCategory from '@hooks/search/atoms/useSearchCategory'; import useSearchValue from '@hooks/search/atoms/useSearchValue'; import useSearchCanRefetch from '@hooks/search/atoms/useSearchCanRefetch'; import GeneralError from '@pages/errors/general'; +import SearchListItem from '@components/search/SearchListItem'; function SearchList() { const { searchCategory } = useSearchCategory(); @@ -26,6 +27,8 @@ function SearchList() { canRefetch: searchCanRefetch, }); + const onRenderSearchItem = useCallback((item: MultiCategoryDetails, index: number) => (), [isLoading]) + if (searchCanRefetch && typeof remove === 'function') { setSearchCanRefetch(false); @@ -50,17 +53,7 @@ function SearchList() { disabled: !data || isLoading || !data?.length }} dataSource={data} - renderItem={(item: MultiCategoryDetails, index) => ( - - - {item.name || item.title} } - description={(item.films && `Appears in episodes ${item.films?.map((item) => item.match(/\d+/)).join(', ')}`) || 'No episodes founds'} - /> - - - )} + renderItem={onRenderSearchItem} /> ); } diff --git a/src/components/search/SearchListItem.tsx b/src/components/search/SearchListItem.tsx new file mode 100644 index 0000000..1a05cf4 --- /dev/null +++ b/src/components/search/SearchListItem.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { Link } from "react-router-dom"; +import { Skeleton, List } from 'antd'; +import { MultiCategoryDetails } from '@api/endpoints/profile'; + +interface SearchListItemStruct { + isLoading: boolean | undefined, + index: number; + item: MultiCategoryDetails; +} + +function SearchListItem({ isLoading = false, index, item }: SearchListItemStruct) { + return ( + + + {item.name || item.title} } + description={(item.films && `Appears in episodes ${item.films?.map((item) => item.match(/\d+/)).join(', ')}`) || 'No episodes founds'} + /> + + ) +} + +export default SearchListItem; \ No newline at end of file From b2814f472e5d0cb21f65de3f1b062fbdf03d000b Mon Sep 17 00:00:00 2001 From: AMW - Game & Entertainment Date: Sat, 27 Aug 2022 11:40:09 +0200 Subject: [PATCH 03/11] feat: Added missing interfaces for components --- src/components/profile/ProfileContent.tsx | 15 +++++++++++---- src/components/profile/RelatedProfileList.tsx | 12 +++++++++--- src/components/profile/RelatedProfileTabs.tsx | 16 ++++++++++++---- src/components/search/SearchListItem.tsx | 4 ++-- 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/components/profile/ProfileContent.tsx b/src/components/profile/ProfileContent.tsx index 75d4537..47802bf 100644 --- a/src/components/profile/ProfileContent.tsx +++ b/src/components/profile/ProfileContent.tsx @@ -2,13 +2,20 @@ import { Descriptions } from 'antd'; import { MultiCategoryDetails } from '@api/endpoints/profile'; import { toCapitalize } from '@utils/text'; -const ProfileContent = ({ data = {} as Partial, column = 2 }) => ( +interface ProfileContentStruct { + data: { + [Property in keyof Partial]: Partial[Property]; + }, + column?: number +} + +const ProfileContent = ({ data, column = 2 }: ProfileContentStruct) => ( { Object.keys(data) - .map((key: string, index: number) => - - {data[key as keyof MultiCategoryDetails] as string} + .map((key, index: number) => + + {data[key as keyof MultiCategoryDetails]?.toString()} ) } diff --git a/src/components/profile/RelatedProfileList.tsx b/src/components/profile/RelatedProfileList.tsx index 789df39..a7d9300 100644 --- a/src/components/profile/RelatedProfileList.tsx +++ b/src/components/profile/RelatedProfileList.tsx @@ -5,15 +5,21 @@ import { useProfile } from '@hooks/profile/useProfile'; import GeneralError from '@pages/errors/general'; import { toCapitalize } from '@utils/text'; -function RelatedProfileList({ categories = [], profileId, list = [] }: any) { +interface RelatedProfileListStruct { + categories?: string[] + profileId: number, + endpointsRelated: string[] +} + +function RelatedProfileList({ categories = [], profileId, endpointsRelated = [] }: RelatedProfileListStruct) { let currentCategory: string | null = null; - const ids = list.map((endpoint: string) => { + const ids = endpointsRelated.map((endpoint: string) => { const [category, currentId] = endpoint.replace('https://swapi.dev/api', '').split('/').filter((item) => item); currentCategory = category; - return currentId; + return parseInt(currentId); }) diff --git a/src/components/profile/RelatedProfileTabs.tsx b/src/components/profile/RelatedProfileTabs.tsx index e426c9a..dc1b687 100644 --- a/src/components/profile/RelatedProfileTabs.tsx +++ b/src/components/profile/RelatedProfileTabs.tsx @@ -1,11 +1,19 @@ import { Tabs } from 'antd'; import { toCapitalize } from '@utils/text'; import RelatedProfileList from "@components/profile/RelatedProfileList"; -import { MultiCategoryDetails } from '@api/endpoints/profile'; -import { SearchCategory } from '@api/endpoints/search'; const { TabPane } = Tabs; -function RelatedProfileTabs({ currentCategory = '', profileId = 0, categories = [] as SearchCategory[], profiles = [] as unknown as { [x: string]: MultiCategoryDetails[] } }) { + +interface RelatedProfileTabsStruct { + currentCategory: string + profileId: number + categories: string[] + profiles: { + [x: string]: string[] + } +} + +function RelatedProfileTabs({ currentCategory, profileId, categories, profiles }: RelatedProfileTabsStruct) { return ( { @@ -13,7 +21,7 @@ function RelatedProfileTabs({ currentCategory = '', profileId = 0, categories = .filter((key: string) => key !== currentCategory) .map((relatedProfileCategory: string, index) => - + ) } diff --git a/src/components/search/SearchListItem.tsx b/src/components/search/SearchListItem.tsx index 1a05cf4..3003fc3 100644 --- a/src/components/search/SearchListItem.tsx +++ b/src/components/search/SearchListItem.tsx @@ -4,12 +4,12 @@ import { Skeleton, List } from 'antd'; import { MultiCategoryDetails } from '@api/endpoints/profile'; interface SearchListItemStruct { - isLoading: boolean | undefined, + isLoading?: boolean | undefined, index: number; item: MultiCategoryDetails; } -function SearchListItem({ isLoading = false, index, item }: SearchListItemStruct) { +function SearchListItem({ isLoading, index, item }: SearchListItemStruct) { return ( From df2459d4a2448b0dfbb59d58bf0613e9cc22407c Mon Sep 17 00:00:00 2001 From: AMW - Game & Entertainment Date: Sat, 27 Aug 2022 11:40:25 +0200 Subject: [PATCH 04/11] feat: Separeted logic into hooks --- src/hooks/profile/useDisplayableDetails.ts | 16 +++++++++ src/hooks/profile/useGetRelatedProfiles.ts | 20 +++++++++++ src/pages/profile/index.tsx | 40 +++++----------------- 3 files changed, 44 insertions(+), 32 deletions(-) create mode 100644 src/hooks/profile/useDisplayableDetails.ts create mode 100644 src/hooks/profile/useGetRelatedProfiles.ts diff --git a/src/hooks/profile/useDisplayableDetails.ts b/src/hooks/profile/useDisplayableDetails.ts new file mode 100644 index 0000000..aeab297 --- /dev/null +++ b/src/hooks/profile/useDisplayableDetails.ts @@ -0,0 +1,16 @@ +import { MultiCategoryDetails } from "@api/endpoints/profile"; + +export const useDisplayableDetails = (viewableCategories: string[], currentProfile: MultiCategoryDetails) => { + return Object.keys(currentProfile) + .filter((key: string) => ![ + ...viewableCategories, + 'homeworld', + 'url', + 'name' + ].includes(key)) + .reduce((previous: any, currentValue) => { + previous[currentValue] = currentProfile[currentValue as keyof MultiCategoryDetails]; + + return previous; + }, {} as unknown as { [x: string]: string[] }) as Partial; +} \ No newline at end of file diff --git a/src/hooks/profile/useGetRelatedProfiles.ts b/src/hooks/profile/useGetRelatedProfiles.ts new file mode 100644 index 0000000..20a714d --- /dev/null +++ b/src/hooks/profile/useGetRelatedProfiles.ts @@ -0,0 +1,20 @@ +import { MultiCategoryDetails } from "@api/endpoints/profile"; + +export const useGetRelatedProfiles = (viewableCategories: string[], currentProfile: MultiCategoryDetails) => { + return ([...viewableCategories, 'homeworld'] as unknown as (keyof MultiCategoryDetails)[]) + .filter((item: keyof MultiCategoryDetails) => typeof currentProfile[item] === 'object' && ((currentProfile[item] || []) as string[]).length > 0) + .reduce((previous, currentValue) => { + + if (!previous[currentValue]){ + previous[currentValue] = []; + } + + if (typeof currentProfile[currentValue] === 'string') { + previous[currentValue].push(...[currentProfile[currentValue] as string]) + } else if (typeof currentProfile[currentValue] === 'object') { + previous[currentValue].push(...(currentProfile[currentValue] as string[] || [])) + } + + return previous; + }, {} as any) +} \ No newline at end of file diff --git a/src/pages/profile/index.tsx b/src/pages/profile/index.tsx index 8d88d50..868e1fe 100644 --- a/src/pages/profile/index.tsx +++ b/src/pages/profile/index.tsx @@ -8,6 +8,8 @@ import ProfileContent from '@components/profile/ProfileContent' import RelatedProfileTabs from "@components/profile/RelatedProfileTabs"; import GeneralError from "@pages/errors/general"; import { categoryToReadable } from "@utils/readable"; +import { useGetRelatedProfiles } from "@hooks/profile/useGetRelatedProfiles"; +import { useDisplayableDetails } from "@hooks/profile/useDisplayableDetails"; const viewableCategories = Object.values(SearchCategory).filter((currentCategory) => currentCategory !== SearchCategory.ALL); @@ -28,6 +30,12 @@ function Profile() { subIds: [profileId], }); + + const [currentProfile = {} as MultiCategoryDetails,] = data; + + const relatedProfiles = useGetRelatedProfiles(viewableCategories, currentProfile) + const displayData = useDisplayableDetails(viewableCategories, currentProfile) + const onErrorRetry = useCallback(() => { navigation(`/${category}/${id}`, { replace: true, @@ -46,38 +54,6 @@ function Profile() { return () } - const [currentProfile] = data; - - const relatedProfiles = ([...viewableCategories, 'homeworld'] as unknown as (keyof MultiCategoryDetails)[]) - .filter((item: keyof MultiCategoryDetails) => typeof currentProfile[item] === 'object' && ((currentProfile[item] || []) as string[]).length > 0) - .reduce((previous, currentValue) => { - - if (!previous[currentValue]){ - previous[currentValue] = []; - } - - if (typeof currentProfile[currentValue] === 'string') { - previous[currentValue].push(...[currentProfile[currentValue] as string]) - } else if (typeof currentProfile[currentValue] === 'object') { - previous[currentValue].push(...(currentProfile[currentValue] as string[] || [])) - } - - return previous; - }, {} as any) - - const displayData = Object.keys(currentProfile) - .filter((key: string) => ![ - ...viewableCategories, - 'homeworld', - 'url', - 'name' - ].includes(key)) - .reduce((previous: any, currentValue) => { - previous[currentValue] = currentProfile[currentValue as keyof MultiCategoryDetails]; - - return previous; - }, {} as unknown as { [x: string]: string[] }) as Partial; - return ( Date: Sat, 27 Aug 2022 18:20:47 +0200 Subject: [PATCH 05/11] feat: Added memorizing --- src/components/profile/ProfileContent.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/profile/ProfileContent.tsx b/src/components/profile/ProfileContent.tsx index 47802bf..f1507a4 100644 --- a/src/components/profile/ProfileContent.tsx +++ b/src/components/profile/ProfileContent.tsx @@ -1,3 +1,4 @@ +import { memo } from 'react'; import { Descriptions } from 'antd'; import { MultiCategoryDetails } from '@api/endpoints/profile'; import { toCapitalize } from '@utils/text'; @@ -22,4 +23,4 @@ const ProfileContent = ({ data, column = 2 }: ProfileContentStruct) => ( ); -export default ProfileContent; \ No newline at end of file +export default memo(ProfileContent); \ No newline at end of file From a04bab2264dc4c0f8e7b8515eeb019f3fdffbc4e Mon Sep 17 00:00:00 2001 From: AMW - Game & Entertainment Date: Sat, 27 Aug 2022 18:21:06 +0200 Subject: [PATCH 06/11] feat: Added more hooks for related profiles --- src/components/profile/RelatedProfileList.tsx | 47 +++---------------- src/hooks/profile/useDisplayableDetails.ts | 12 +++-- src/hooks/profile/useProfileTableColumns.ts | 33 +++++++++++++ src/hooks/profile/useProfileTableRows.ts | 25 ++++++++++ 4 files changed, 74 insertions(+), 43 deletions(-) create mode 100644 src/hooks/profile/useProfileTableColumns.ts create mode 100644 src/hooks/profile/useProfileTableRows.ts diff --git a/src/components/profile/RelatedProfileList.tsx b/src/components/profile/RelatedProfileList.tsx index a7d9300..e3e1dd1 100644 --- a/src/components/profile/RelatedProfileList.tsx +++ b/src/components/profile/RelatedProfileList.tsx @@ -2,8 +2,9 @@ import { Table } from 'antd'; import { MultiCategoryDetails } from '@api/endpoints/profile'; import { SearchCategory } from '@api/endpoints/search'; import { useProfile } from '@hooks/profile/useProfile'; -import GeneralError from '@pages/errors/general'; -import { toCapitalize } from '@utils/text'; +import GeneralError from '@pages/errors/general' +import { useProfileTableColumns } from '@hooks/profile/useProfileTableColumns'; +import { useProfileTableRows } from '@hooks/profile/useProfileTableRows'; interface RelatedProfileListStruct { categories?: string[] @@ -32,6 +33,10 @@ function RelatedProfileList({ categories = [], profileId, endpointsRelated = [] profileId, subIds: ids, }); + const displayData = useProfileTableRows(categories, data) + const columns = useProfileTableColumns(categories, data) + + console.log('data', data, displayData) if (isError) { return () @@ -41,44 +46,6 @@ function RelatedProfileList({ categories = [], profileId, endpointsRelated = [] return () } - const displayData = data - .map((currentProfile: MultiCategoryDetails) => Object.keys(currentProfile) - .filter((key: string) => ![ - ...categories, - 'homeworld', - 'characters', - 'url', - ].includes(key)) - .reduce((previous: any, currentValue) => { - previous[currentValue] = currentProfile[currentValue as keyof MultiCategoryDetails]; - return previous; - }, {} as unknown as { [x: string]: string[] }) - ) - .map((currentProfile: MultiCategoryDetails, index) => ({ - ...currentProfile, - key: `${(currentProfile.name || currentProfile.title || '').split(' ').join('-')}-${index}`, - })); - - const [currentProfile = [] as unknown as MultiCategoryDetails,] = data; - - const columns = Object.keys(currentProfile) - .filter((key: string) => ![ - ...categories, - 'homeworld', - 'characters', - 'url', - ].includes(key)) - .map((key, index) => ({ - title: toCapitalize(key?.toString().replace(/([_])/gi, ' ')), - dataIndex: key, - key: `${key}-${index}`, - width: 'auto', - ellipsis: true, - fixed: true, - })); - - console.log('displayData', displayData) - return (
{ +type UseDisplayableDetailsStruct = (MultiCategoryDetails & { + key: string +}) + +export const useDisplayableDetails = (viewableCategories: string[], currentProfile: MultiCategoryDetails): UseDisplayableDetailsStruct => { return Object.keys(currentProfile) .filter((key: string) => ![ ...viewableCategories, 'homeworld', 'url', + 'characters', 'name' ].includes(key)) + .reduce((previous: any, currentValue) => { previous[currentValue] = currentProfile[currentValue as keyof MultiCategoryDetails]; - + return previous; - }, {} as unknown as { [x: string]: string[] }) as Partial; + }, {} as unknown as { [x: string]: string[] }) } \ No newline at end of file diff --git a/src/hooks/profile/useProfileTableColumns.ts b/src/hooks/profile/useProfileTableColumns.ts new file mode 100644 index 0000000..9c60c4d --- /dev/null +++ b/src/hooks/profile/useProfileTableColumns.ts @@ -0,0 +1,33 @@ +import { MultiCategoryDetails } from "@api/endpoints/profile"; +import { toCapitalize } from "@utils/text"; + +interface UserProfileTableColumnStruct { + title: string + dataIndex: string + key: string + width: string | 'auto' + ellipsis: boolean + fixed: boolean +} + +type UseProfileTableColumnsStruct = UserProfileTableColumnStruct[] + +export const useProfileTableColumns = (categories: string[], data: MultiCategoryDetails[]): UseProfileTableColumnsStruct => { + const [columnDetails = {} as MultiCategoryDetails] = data; + + return Object.keys(columnDetails) + .filter((key: string) => ![ + ...categories, + 'homeworld', + 'characters', + 'url', + ].includes(key)) + .map((key, index) => ({ + title: toCapitalize(key?.toString().replace(/([_])/gi, ' ')), + dataIndex: key, + key: `${key}-${index}`, + width: 'auto', + ellipsis: true, + fixed: true, + })); +} \ No newline at end of file diff --git a/src/hooks/profile/useProfileTableRows.ts b/src/hooks/profile/useProfileTableRows.ts new file mode 100644 index 0000000..da79206 --- /dev/null +++ b/src/hooks/profile/useProfileTableRows.ts @@ -0,0 +1,25 @@ +import { MultiCategoryDetails } from "@api/endpoints/profile"; + +type UseProfileTableRowsStruct = (MultiCategoryDetails & { + key: string +})[] + +export const useProfileTableRows = (viewableCategories: string[], data: MultiCategoryDetails[], max?: number): UseProfileTableRowsStruct => { + return data.map((currentProfile: MultiCategoryDetails) => Object.keys(currentProfile) + .filter((key: string) => ![ + ...viewableCategories, + 'homeworld', + 'url', + 'characters', + ].includes(key)) + + .reduce((previous: any, currentValue) => { + previous[currentValue] = currentProfile[currentValue as keyof MultiCategoryDetails]; + + return previous; + }, {} as unknown as { [x: string]: string[] })) + .map((currentProfile: MultiCategoryDetails, index: number) => ({ + ...currentProfile, + key: `${(currentProfile.name || currentProfile.title || '').split(' ').join('-')}-${index}`, + })); +} \ No newline at end of file From 37ef6365ce50c58eb4fd771cad74fc6fae426f74 Mon Sep 17 00:00:00 2001 From: AMW - Game & Entertainment Date: Sat, 27 Aug 2022 18:34:33 +0200 Subject: [PATCH 07/11] feat: Split more the code to use hooks --- src/components/profile/RelatedProfileList.tsx | 18 +++++------------- src/components/search/SearchListItem.tsx | 9 ++++++--- src/hooks/profile/useGetProfileCategories.ts | 7 +++++++ src/hooks/profile/useGetProfileEpisodeIds.ts | 1 + src/hooks/profile/useGetProfileIds.ts | 7 +++++++ 5 files changed, 26 insertions(+), 16 deletions(-) create mode 100644 src/hooks/profile/useGetProfileCategories.ts create mode 100644 src/hooks/profile/useGetProfileEpisodeIds.ts create mode 100644 src/hooks/profile/useGetProfileIds.ts diff --git a/src/components/profile/RelatedProfileList.tsx b/src/components/profile/RelatedProfileList.tsx index e3e1dd1..4322cfb 100644 --- a/src/components/profile/RelatedProfileList.tsx +++ b/src/components/profile/RelatedProfileList.tsx @@ -5,6 +5,8 @@ import { useProfile } from '@hooks/profile/useProfile'; import GeneralError from '@pages/errors/general' import { useProfileTableColumns } from '@hooks/profile/useProfileTableColumns'; import { useProfileTableRows } from '@hooks/profile/useProfileTableRows'; +import { useGetProfileCategories } from '@hooks/profile/useGetProfileCategories'; +import { useGetProfileIds } from '@hooks/profile/useGetProfileIds'; interface RelatedProfileListStruct { categories?: string[] @@ -13,30 +15,20 @@ interface RelatedProfileListStruct { } function RelatedProfileList({ categories = [], profileId, endpointsRelated = [] }: RelatedProfileListStruct) { - let currentCategory: string | null = null; - - const ids = endpointsRelated.map((endpoint: string) => { - const [category, currentId] = endpoint.replace('https://swapi.dev/api', '').split('/').filter((item) => item); - - currentCategory = category; - - return parseInt(currentId); - }) - + const category = useGetProfileCategories(endpointsRelated); + const ids = useGetProfileIds(endpointsRelated); const { isLoading, isError, data, } = useProfile({ - category: currentCategory as unknown as SearchCategory, + category: category as unknown as SearchCategory, profileId, subIds: ids, }); const displayData = useProfileTableRows(categories, data) const columns = useProfileTableColumns(categories, data) - - console.log('data', data, displayData) if (isError) { return () diff --git a/src/components/search/SearchListItem.tsx b/src/components/search/SearchListItem.tsx index 3003fc3..7c66a40 100644 --- a/src/components/search/SearchListItem.tsx +++ b/src/components/search/SearchListItem.tsx @@ -1,7 +1,8 @@ -import React from 'react'; +import React, { memo } from 'react'; import { Link } from "react-router-dom"; import { Skeleton, List } from 'antd'; import { MultiCategoryDetails } from '@api/endpoints/profile'; +import { useGetProfileEpisodesIds } from '@hooks/profile/useGetProfileEpisodeIds'; interface SearchListItemStruct { isLoading?: boolean | undefined, @@ -10,16 +11,18 @@ interface SearchListItemStruct { } function SearchListItem({ isLoading, index, item }: SearchListItemStruct) { + const episodesIds = useGetProfileEpisodesIds(item.films); + return ( {item.name || item.title} } - description={(item.films && `Appears in episodes ${item.films?.map((item) => item.match(/\d+/)).join(', ')}`) || 'No episodes founds'} + description={(item.films && `Appears in episodes ${episodesIds.join(',')}`) || 'No episodes founds'} /> ) } -export default SearchListItem; \ No newline at end of file +export default memo(SearchListItem); \ No newline at end of file diff --git a/src/hooks/profile/useGetProfileCategories.ts b/src/hooks/profile/useGetProfileCategories.ts new file mode 100644 index 0000000..1acc225 --- /dev/null +++ b/src/hooks/profile/useGetProfileCategories.ts @@ -0,0 +1,7 @@ +export const useGetProfileCategories = (endpointsRelated: string[]): string => { + const [first] = endpointsRelated; + + const [category] = first.replace('https://swapi.dev/api', '').split('/').filter((item) => item); + + return category; +} \ No newline at end of file diff --git a/src/hooks/profile/useGetProfileEpisodeIds.ts b/src/hooks/profile/useGetProfileEpisodeIds.ts new file mode 100644 index 0000000..b5e761a --- /dev/null +++ b/src/hooks/profile/useGetProfileEpisodeIds.ts @@ -0,0 +1 @@ +export const useGetProfileEpisodesIds = (films: string[] = []) => films.map((item) => item.match(/\d+/)) \ No newline at end of file diff --git a/src/hooks/profile/useGetProfileIds.ts b/src/hooks/profile/useGetProfileIds.ts new file mode 100644 index 0000000..31c3221 --- /dev/null +++ b/src/hooks/profile/useGetProfileIds.ts @@ -0,0 +1,7 @@ +export const useGetProfileIds = (endpointsRelated: string[]): number[] => { + return endpointsRelated.map((endpoint: string) => { + const [, currentId] = endpoint.replace('https://swapi.dev/api', '').split('/').filter((item) => item); + + return parseInt(currentId); + }) +} \ No newline at end of file From c78149b89a8f0e7432488a4e4e9a3ee5965cc5f3 Mon Sep 17 00:00:00 2001 From: AMW - Game & Entertainment Date: Sat, 27 Aug 2022 18:48:33 +0200 Subject: [PATCH 08/11] feat: Added more memo and useEffect for setting up a value --- src/components/profile/RelatedProfileTabs.tsx | 3 ++- src/components/search/SearchList.tsx | 16 +++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/components/profile/RelatedProfileTabs.tsx b/src/components/profile/RelatedProfileTabs.tsx index dc1b687..eb7f2c5 100644 --- a/src/components/profile/RelatedProfileTabs.tsx +++ b/src/components/profile/RelatedProfileTabs.tsx @@ -1,6 +1,7 @@ import { Tabs } from 'antd'; import { toCapitalize } from '@utils/text'; import RelatedProfileList from "@components/profile/RelatedProfileList"; +import { memo } from 'react'; const { TabPane } = Tabs; @@ -28,4 +29,4 @@ function RelatedProfileTabs({ currentCategory, profileId, categories, profiles } ) } -export default RelatedProfileTabs; \ No newline at end of file +export default memo(RelatedProfileTabs); \ No newline at end of file diff --git a/src/components/search/SearchList.tsx b/src/components/search/SearchList.tsx index d4c5926..09c6b00 100644 --- a/src/components/search/SearchList.tsx +++ b/src/components/search/SearchList.tsx @@ -1,4 +1,4 @@ -import React, { useCallback } from 'react'; +import React, { memo, useCallback, useEffect } from 'react'; import { useNavigate } from "react-router-dom"; import { List } from 'antd'; import { useSearch } from '@hooks/search/useSearch' @@ -12,8 +12,8 @@ import SearchListItem from '@components/search/SearchListItem'; function SearchList() { const { searchCategory } = useSearchCategory(); - const { searchCanRefetch, setSearchCanRefetch } = useSearchCanRefetch(); const { searchValue } = useSearchValue(); + const { searchCanRefetch, setSearchCanRefetch } = useSearchCanRefetch(); const navigation = useNavigate(); const { @@ -29,11 +29,13 @@ function SearchList() { const onRenderSearchItem = useCallback((item: MultiCategoryDetails, index: number) => (), [isLoading]) - if (searchCanRefetch && typeof remove === 'function') { - setSearchCanRefetch(false); + useEffect(() => { + if (searchCanRefetch && typeof remove === 'function') { + setSearchCanRefetch(false); - remove() - } + remove() + } + }, [remove, searchCanRefetch, searchCategory, setSearchCanRefetch]) const onErrorRetry = useCallback(() => { navigation(`/search/${searchCategory}?search=${searchValue}`, { @@ -58,4 +60,4 @@ function SearchList() { ); } -export default SearchList; \ No newline at end of file +export default memo(SearchList); \ No newline at end of file From 18e9365f22f0c84870aa64f0b9aa9432b3ca07fb Mon Sep 17 00:00:00 2001 From: AMW - Game & Entertainment Date: Sat, 27 Aug 2022 18:50:12 +0200 Subject: [PATCH 09/11] feat: Added another memo for another list of related profile --- src/components/profile/RelatedProfileList.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/profile/RelatedProfileList.tsx b/src/components/profile/RelatedProfileList.tsx index 4322cfb..7e04ccd 100644 --- a/src/components/profile/RelatedProfileList.tsx +++ b/src/components/profile/RelatedProfileList.tsx @@ -7,6 +7,7 @@ import { useProfileTableColumns } from '@hooks/profile/useProfileTableColumns'; import { useProfileTableRows } from '@hooks/profile/useProfileTableRows'; import { useGetProfileCategories } from '@hooks/profile/useGetProfileCategories'; import { useGetProfileIds } from '@hooks/profile/useGetProfileIds'; +import { memo } from 'react'; interface RelatedProfileListStruct { categories?: string[] @@ -44,4 +45,4 @@ function RelatedProfileList({ categories = [], profileId, endpointsRelated = [] }} />); } -export default RelatedProfileList; \ No newline at end of file +export default memo(RelatedProfileList); \ No newline at end of file From 4acfbb9bbc0f7c5924d52913283ffc9bd449e55b Mon Sep 17 00:00:00 2001 From: AMW - Game & Entertainment Date: Sun, 28 Aug 2022 16:17:13 +0200 Subject: [PATCH 10/11] feat: Removed china china china --- package-lock.json | 146 ++++++++++++++----------------------- package.json | 2 +- src/pages/search/index.tsx | 14 ++-- 3 files changed, 61 insertions(+), 101 deletions(-) diff --git a/package-lock.json b/package-lock.json index cfc6367..9ef92a0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,9 +17,9 @@ "@types/node": "^16.11.47", "@types/react": "^18.0.17", "@types/react-dom": "^18.0.6", - "ahooks": "^3.7.0", "antd": "^4.22.4", "axios": "^0.27.2", + "beautiful-react-hooks": "^3.11.1", "craco": "^0.0.3", "history": "^5.3.0", "react": "^18.2.0", @@ -3994,11 +3994,6 @@ "pretty-format": "^27.0.0" } }, - "node_modules/@types/js-cookie": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz", - "integrity": "sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==" - }, "node_modules/@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", @@ -4797,32 +4792,6 @@ "node": ">= 6.0.0" } }, - "node_modules/ahooks": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/ahooks/-/ahooks-3.7.0.tgz", - "integrity": "sha512-IOZ6IpVeAd7aWtV2O+dBmCQc0aHt+WPG3B5tPHnVVcPnEq9FDJxx8IIA5hLxN4lRa1m1ZMx6pOE2rrYW7bjU6A==", - "dependencies": { - "@types/js-cookie": "^2.x.x", - "ahooks-v3-count": "^1.0.0", - "dayjs": "^1.9.1", - "intersection-observer": "^0.12.0", - "js-cookie": "^2.x.x", - "lodash": "^4.17.21", - "resize-observer-polyfill": "^1.5.1", - "screenfull": "^5.0.0" - }, - "engines": { - "node": ">=8.0.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/ahooks-v3-count": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ahooks-v3-count/-/ahooks-v3-count-1.0.0.tgz", - "integrity": "sha512-V7uUvAwnimu6eh/PED4mCDjE7tokeZQLKlxg9lCTMPhN+NjsSbtdacByVlR1oluXQzD3MOw55wylDmQo4+S9ZQ==" - }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -5658,6 +5627,21 @@ "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" }, + "node_modules/beautiful-react-hooks": { + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/beautiful-react-hooks/-/beautiful-react-hooks-3.11.1.tgz", + "integrity": "sha512-uXeli3YYvo15+5xFvRm/rpBtVQ1SrelVTDKPZAlBWhaY8FXQegjKpWC1TjUL5noBMtWjDtx/rPaoCNlRtqJO0g==", + "dependencies": { + "lodash.debounce": "^4.0.8", + "lodash.throttle": "^4.1.1" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0", + "react-router-dom": ">=5.0.0", + "rxjs": ">=7.0.0" + } + }, "node_modules/bfj": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.0.2.tgz", @@ -11084,11 +11068,6 @@ "node": ">= 0.4" } }, - "node_modules/intersection-observer": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.12.2.tgz", - "integrity": "sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==" - }, "node_modules/ipaddr.js": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", @@ -13472,11 +13451,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/js-cookie": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz", - "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==" - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -13807,6 +13781,11 @@ "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==" + }, "node_modules/lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -18188,6 +18167,15 @@ "aproba": "^1.1.1" } }, + "node_modules/rxjs": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.6.tgz", + "integrity": "sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==", + "peer": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -18289,17 +18277,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/screenfull": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/screenfull/-/screenfull-5.2.0.tgz", - "integrity": "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==", - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/scroll-into-view-if-needed": { "version": "2.2.29", "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz", @@ -24262,11 +24239,6 @@ "pretty-format": "^27.0.0" } }, - "@types/js-cookie": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz", - "integrity": "sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==" - }, "@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", @@ -24930,26 +24902,6 @@ "debug": "4" } }, - "ahooks": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/ahooks/-/ahooks-3.7.0.tgz", - "integrity": "sha512-IOZ6IpVeAd7aWtV2O+dBmCQc0aHt+WPG3B5tPHnVVcPnEq9FDJxx8IIA5hLxN4lRa1m1ZMx6pOE2rrYW7bjU6A==", - "requires": { - "@types/js-cookie": "^2.x.x", - "ahooks-v3-count": "^1.0.0", - "dayjs": "^1.9.1", - "intersection-observer": "^0.12.0", - "js-cookie": "^2.x.x", - "lodash": "^4.17.21", - "resize-observer-polyfill": "^1.5.1", - "screenfull": "^5.0.0" - } - }, - "ahooks-v3-count": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ahooks-v3-count/-/ahooks-v3-count-1.0.0.tgz", - "integrity": "sha512-V7uUvAwnimu6eh/PED4mCDjE7tokeZQLKlxg9lCTMPhN+NjsSbtdacByVlR1oluXQzD3MOw55wylDmQo4+S9ZQ==" - }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -25579,6 +25531,15 @@ "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" }, + "beautiful-react-hooks": { + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/beautiful-react-hooks/-/beautiful-react-hooks-3.11.1.tgz", + "integrity": "sha512-uXeli3YYvo15+5xFvRm/rpBtVQ1SrelVTDKPZAlBWhaY8FXQegjKpWC1TjUL5noBMtWjDtx/rPaoCNlRtqJO0g==", + "requires": { + "lodash.debounce": "^4.0.8", + "lodash.throttle": "^4.1.1" + } + }, "bfj": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.0.2.tgz", @@ -29726,11 +29687,6 @@ "side-channel": "^1.0.4" } }, - "intersection-observer": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.12.2.tgz", - "integrity": "sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==" - }, "ipaddr.js": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", @@ -31446,11 +31402,6 @@ } } }, - "js-cookie": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz", - "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==" - }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -31707,6 +31658,11 @@ "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" }, + "lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==" + }, "lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -34771,6 +34727,15 @@ "aproba": "^1.1.1" } }, + "rxjs": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.6.tgz", + "integrity": "sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==", + "peer": true, + "requires": { + "tslib": "^2.1.0" + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -34834,11 +34799,6 @@ "ajv-keywords": "^3.5.2" } }, - "screenfull": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/screenfull/-/screenfull-5.2.0.tgz", - "integrity": "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==" - }, "scroll-into-view-if-needed": { "version": "2.2.29", "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz", diff --git a/package.json b/package.json index c9f5662..14a192a 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,9 @@ "@types/node": "^16.11.47", "@types/react": "^18.0.17", "@types/react-dom": "^18.0.6", - "ahooks": "^3.7.0", "antd": "^4.22.4", "axios": "^0.27.2", + "beautiful-react-hooks": "^3.11.1", "craco": "^0.0.3", "history": "^5.3.0", "react": "^18.2.0", diff --git a/src/pages/search/index.tsx b/src/pages/search/index.tsx index c01e368..979748b 100644 --- a/src/pages/search/index.tsx +++ b/src/pages/search/index.tsx @@ -1,11 +1,13 @@ -import React, { useCallback } from 'react'; +import { useCallback } from 'react'; import { Outlet, useParams, useNavigate } from "react-router-dom"; import type { RadioChangeEvent } from 'antd'; import { Radio, Input } from 'antd'; import { SearchCategory } from '@api/endpoints/search'; import useSearchCategory from '@hooks/search/atoms/useSearchCategory'; import useSearchValue from '@hooks/search/atoms/useSearchValue'; -import { useMount, useThrottleFn, useDebounceEffect } from 'ahooks'; +import useDidMount from 'beautiful-react-hooks/useDidMount'; +import useThrottledCallback from 'beautiful-react-hooks/useThrottledCallback'; +import useDebouncedCallback from 'beautiful-react-hooks/useDebouncedCallback'; import { useNavQuery } from '@hooks/navigation/useNavQuery'; import useSearchCanRefetch from '@hooks/search/atoms/useSearchCanRefetch'; @@ -20,7 +22,7 @@ function MainSearch() { const { search: querySearchValue } = useNavQuery('search'); const navigation = useNavigate(); - useMount(() => { + useDidMount(() => { if (category) { setSearchCategory(category as SearchCategory) } @@ -36,7 +38,7 @@ function MainSearch() { } }) - const { run: onChange } = useThrottleFn( + const onChange = useThrottledCallback( (e: RadioChangeEvent) => { const newCategory = e.target.value; @@ -48,10 +50,9 @@ function MainSearch() { }); } }, - { wait: 500 }, ); - useDebounceEffect( + useDebouncedCallback( () => { setSearchCanRefetch(category !== searchCategory || searchValue !== querySearchValue) @@ -62,7 +63,6 @@ function MainSearch() { } }, [searchValue, querySearchValue, category, searchCategory], - { wait: 1000 }, ); const onSearch = useCallback((value: string) => { From b2a8533e22c573c6baed6458d53d867a967ced0e Mon Sep 17 00:00:00 2001 From: AMW - Game & Entertainment Date: Tue, 30 Aug 2022 13:07:00 +0200 Subject: [PATCH 11/11] feat: Latest updated --- README.md | 158 +- TASK.md | 99 + craco.config.js | 30 +- package-lock.json | 1597 +++++++++-------- package.json | 3 + src/App.css | 50 +- src/App.test.tsx | 28 +- src/api/endpoints/profile.ts | 15 +- src/api/endpoints/search.ts | 11 + src/components/profile/RelatedProfileList.tsx | 2 +- src/components/profile/RelatedProfileTabs.tsx | 2 +- src/components/search/SearchList.tsx | 4 +- src/components/search/SearchListItem.tsx | 4 +- .../profile/useDisplayableDetails.test.ts | 51 + src/hooks/profile/useDisplayableDetails.ts | 4 +- .../profile/useGetProfileCategories.test.ts | 29 + src/hooks/profile/useGetProfileCategories.ts | 6 +- src/hooks/profile/useGetProfileEpisodeIds.ts | 1 - .../profile/useGetProfileEpisodesIds.test.ts | 33 + src/hooks/profile/useGetProfileEpisodesIds.ts | 5 + src/hooks/profile/useGetProfileIds.test.ts | 33 + .../profile/useGetRelatedProfiles.test.ts | 75 + src/hooks/profile/useProfile.ts | 11 +- .../profile/useProfileTableColumns.test.ts | 56 + src/hooks/profile/useProfileTableColumns.ts | 5 +- src/hooks/profile/useProfileTableRows.test.ts | 60 + src/hooks/profile/useProfileTableRows.ts | 4 +- src/hooks/search/useSearch.ts | 8 + src/index.css | 21 +- src/index.tsx | 2 +- src/pages/errors/404.tsx | 2 +- src/pages/errors/general.tsx | 2 +- src/pages/profile/index.tsx | 9 +- src/pages/search/index.tsx | 2 +- src/{services => plugins}/QueryClient.ts | 4 + src/plugins/routing.tsx | 3 + src/services/ApiService.ts | 3 + src/utils/api.ts | 5 + src/utils/readable.test.ts | 22 + src/utils/readable.ts | 13 +- src/utils/text.test.ts | 35 + src/utils/text.ts | 8 +- 42 files changed, 1604 insertions(+), 911 deletions(-) create mode 100644 TASK.md create mode 100644 src/hooks/profile/useDisplayableDetails.test.ts create mode 100644 src/hooks/profile/useGetProfileCategories.test.ts delete mode 100644 src/hooks/profile/useGetProfileEpisodeIds.ts create mode 100644 src/hooks/profile/useGetProfileEpisodesIds.test.ts create mode 100644 src/hooks/profile/useGetProfileEpisodesIds.ts create mode 100644 src/hooks/profile/useGetProfileIds.test.ts create mode 100644 src/hooks/profile/useGetRelatedProfiles.test.ts create mode 100644 src/hooks/profile/useProfileTableColumns.test.ts create mode 100644 src/hooks/profile/useProfileTableRows.test.ts rename src/{services => plugins}/QueryClient.ts (81%) create mode 100644 src/utils/readable.test.ts create mode 100644 src/utils/text.test.ts diff --git a/README.md b/README.md index d9aff51..9ffc306 100644 --- a/README.md +++ b/README.md @@ -1,86 +1,72 @@ -# Coding Assignment -The goal of this assignment is to build a small React application that lets you search and display information from the Star Wars movies (no knowledge of SW is required). The data needed will be queried from [SWAPI (Star Wars API)](https://swapi.dev/) which is an open testing API. - -## Overview -The app should consist of a front page with a centered search box where you can type a search string and get matching results. Clicking on a result should route to a new page with the search box on top and details about the query underneath. - -### Searching -The search box will be used to query information about people, planets, starships and vehicles. Beneath the search box there should be five radio buttons: -* All (default) -* People -* Planets -* Starships -* Vehicles - -You should use the existing `/search` endpoints for each category (see: https://swapi.dev/documentation#search). -The default behaviour (All) should be to query all four search endpoints and display all results. - -### Search results -The search result page should have the whole search form at the top and the list with results beneath it (much like any other search engine, like google or duckduckgo). -Combined results (`All` selected) should be ordered by category whith the category with most results appearing at the top. - -Each result entry should be listed with it's `name` property taken from the result plus a list of the films in which it appears (provided in the result). -So a result for a search with `query=luke` should look something like: - -``` -Luke Sywalker (appears in: 4, 5, 6, 3) -``` -Where (4, 5, 6, 3) are the `episode_id`s of the films the character appears in. (Don't worry if the results are not up to date as of 2020) - -Generally the useful information from the search response for a single entry is as follows: - -``` -{ - "count": 1, - ... - "results": [ - { - "name": "Luke Skywalker", - ... - "films": [ - "http://swapi.dev/api/films/1/", - "http://swapi.dev/api/films/2/", - "http://swapi.dev/api/films/3/", - "http://swapi.dev/api/films/6/" - ], - ... - "url": "http://swapi.dev/api/people/1/" - } - ] -} -``` - Note: Pagination is not required, but feel free to add more details into the search result entry at your discretion, making anything better will give you bonus points. - -### Detailed view -Each search result entry should be a link routing to a page having the search form at the top and details about the entry beneath it. The url should correspond to the search result entry, so that the the page can be accessed separately. For example if the search result entry url is `http://swapi.dev/api/people/1/` our url should also be `people/1`. -The details displayed should be simple key value pairs displayed as a table (or similar) plus the films in which the thing or person apears in e.g.: - -> **Name:** Luke Skywalker -> **Height:** 172 -> **Hair color:** blond -> **Skin color:** fair -> **Eye color:** blue -> **Gender:** male -> **Movies:** A New Hope, The Empire Strikes Back, Return of the Jedi - -It is not required to include all fields from the result, just a reasonable amount. You get bonus points for displaying information requiring to poll other endpoints (like `Movies` in the example above) - -**Extra Bonus**: Incorporate the detailed view to the side of the search results page implementing a master-detail pattern while also keeping the route to the detail view page. - -## Technical details - -## Requirements -The only strict requirements we pose are that the app is written in **typescript** using the latest version of React. We recommend the use of react patterns wherever meaningful of course, and be prepared to show and explain them when presenting the solution. - -### Project Setup -Please setup the application in a way that we can start it by simply running `npm start` or else provide a simple `start.sh` script. - -### SWAPI -The [SWAPI](https://swapi.dev/) API is a free service and has a 10,000 requests per day rate limiting. Please make sure you don't abuse it. -Note that in some of the results the URLs returned start with `http` which is wrong and should be modified to `https` for them to work, make sure you handle this correctly. - -### External Libraries -We don't mind if you use whatever external libraries you like. - -### Estimation -You will see an open issue "Call for estimation". Please estimate by writing a comment when you think the task will be ready before you start. We don't set any hard deadlines. \ No newline at end of file +# Task Completed + +First of all, thank you for waiting for this much time, unforunately had endless of queries, travel, work, loan, bank, notary related matters which left me with little time back than. The task has been completed, along with the extra bonus points asked. Below will add the list of things introduced along this project. + +## @tanstack/react-query + +This is used to handle the api requests hooks and as well the caching to prevent extra requests unneeded, especially for data that usually doesn't change much. Having redis is important on the backend, yet the frontend should as well cache what is needed to be cached. + +Further more you can see the plugin configuration at `@plugins/QueryClient` + +## beautiful-react-hooks + +Set of hooks that allow us to use general usage hooks such as `useThrottledCallback`, `useDebouceCallback`, `useDidMount`, and many others are avaialble at their docs. + +## craco + +This one would say it is very essential for the following reasons + +- Handles webpack matters without the need to eject the app whne using create react app +- Further Jest configuration + `react-app-rewire-alias` for alias +- Generally used for alias in our case for @name/* + +## React Routing Dom + +We'll know what it is for, and I'm using it for the routing, along with few hooks that we need such as `useNavigation` and `useParams`, you can find it as well used as a hook in `useNavQuery` + +## Axios + +Use this for our api requests handler, which will be combined later with @transtack/react-query hooks + +## antd + +Used this for design, yet generally I do not use this, first of all I do not really use chinese libs, due of certain events acquired around the world. Although the lib is used by many and is amazing, yet got althernatives to it which they're twice as much better. + +## recoil + +Used this for state, which allows cross state component, aka state management. One of good things about it, it is as well minimal + +## Tests + +Added tests generally for the following + +- Testing utils +- Testing hooks +- Testing main app - Could add more for pages if required + +## Structure + +Aimed to provide a good structure for this project, since it is small project as well. + +## Architecture + +The general architecture of how everything is split and designed is to simplify everything as much as possible and remain performant. Introducing of reusability is in place, yet is not too much, as would be tiedly coupled later and would make it bigger problem to split and/or fix if any issue happens. Keep code simple and readable, in fact max of lines doesnt exceed 100 lines for no file. + +## Full Typescript support + +The whole project is full typescript support, including interfaces of the api. + +## Futher improvements that could have been introduced + +- ESlint +- Storyboard +- Further more tests, especially components testing +- Design could have been made more attractive, yet I believe in this task one of most important queries is the performance, as we know react anyone can write it, but not everyone can write it properly, which can end up with endless performance issues. +- Try and reduce more packages from the package, yet kept it to minimum, in fact the maximum a bit of extra package would be `beatiful-react-hooks`. + +## Cheers + +Cheers for the test, looking forward to hear from you + +Best regards, +Red diff --git a/TASK.md b/TASK.md new file mode 100644 index 0000000..bbbbda7 --- /dev/null +++ b/TASK.md @@ -0,0 +1,99 @@ +# Coding Assignment + +The goal of this assignment is to build a small React application that lets you search and display information from the Star Wars movies (no knowledge of SW is required). The data needed will be queried from [SWAPI (Star Wars API)](https://swapi.dev/) which is an open testing API. + +## Overview + +The app should consist of a front page with a centered search box where you can type a search string and get matching results. Clicking on a result should route to a new page with the search box on top and details about the query underneath. + +### Searching + +The search box will be used to query information about people, planets, starships and vehicles. Beneath the search box there should be five radio buttons: + +* All (default) +* People +* Planets +* Starships +* Vehicles + +You should use the existing `/search` endpoints for each category (see: ). +The default behaviour (All) should be to query all four search endpoints and display all results. + +### Search results + +The search result page should have the whole search form at the top and the list with results beneath it (much like any other search engine, like google or duckduckgo). +Combined results (`All` selected) should be ordered by category whith the category with most results appearing at the top. + +Each result entry should be listed with it's `name` property taken from the result plus a list of the films in which it appears (provided in the result). +So a result for a search with `query=luke` should look something like: + +```text +Luke Sywalker (appears in: 4, 5, 6, 3) +``` + +Where (4, 5, 6, 3) are the `episode_id`s of the films the character appears in. (Don't worry if the results are not up to date as of 2020) + +Generally the useful information from the search response for a single entry is as follows: + +```json +{ + "count": 1, + ... + "results": [ + { + "name": "Luke Skywalker", + ... + "films": [ + "http://swapi.dev/api/films/1/", + "http://swapi.dev/api/films/2/", + "http://swapi.dev/api/films/3/", + "http://swapi.dev/api/films/6/" + ], + ... + "url": "http://swapi.dev/api/people/1/" + } + ] +} +``` + + Note: Pagination is not required, but feel free to add more details into the search result entry at your discretion, making anything better will give you bonus points. + +### Detailed view + +Each search result entry should be a link routing to a page having the search form at the top and details about the entry beneath it. The url should correspond to the search result entry, so that the the page can be accessed separately. For example if the search result entry url is `http://swapi.dev/api/people/1/` our url should also be `people/1`. +The details displayed should be simple key value pairs displayed as a table (or similar) plus the films in which the thing or person apears in e.g.: + +> **Name:** Luke Skywalker +> **Height:** 172 +> **Hair color:** blond +> **Skin color:** fair +> **Eye color:** blue +> **Gender:** male +> **Movies:** A New Hope, The Empire Strikes Back, Return of the Jedi + +It is not required to include all fields from the result, just a reasonable amount. You get bonus points for displaying information requiring to poll other endpoints (like `Movies` in the example above) + +**Extra Bonus**: Incorporate the detailed view to the side of the search results page implementing a master-detail pattern while also keeping the route to the detail view page. + +## Technical details + +## Requirements + +The only strict requirements we pose are that the app is written in **typescript** using the latest version of React. We recommend the use of react patterns wherever meaningful of course, and be prepared to show and explain them when presenting the solution. + +### Project Setup + +Please setup the application in a way that we can start it by simply running `npm start` or else provide a simple `start.sh` script. + +### SWAPI + +The [SWAPI](https://swapi.dev/) API is a free service and has a 10,000 requests per day rate limiting. Please make sure you don't abuse it. +Note that in some of the results the URLs returned start with `http` which is wrong and should be modified to `https` for them to work, make sure you handle this correctly. + +### External Libraries + +We don't mind if you use whatever external libraries you like. + +### Estimation + +You will see an open issue "Call for estimation". Please estimate by writing a comment when you think the task will be ready before you start. We don't set any hard deadlines. diff --git a/craco.config.js b/craco.config.js index a742b77..aa811fc 100644 --- a/craco.config.js +++ b/craco.config.js @@ -1,15 +1,21 @@ -const path = require(`path`); +const {CracoAliasPlugin } = require('react-app-rewire-alias') + +const aliasMap = { + "@components": "src/components", + "@pages": "src/pages", + "@hooks": "src/hooks", + "@plugins": "src/plugins", + "@services": "src/services", + "@utils": "src/utils", + "@api": "src/api", + "@app": "src", +} module.exports = { - webpack: { - alias: { - "@components": path.resolve(__dirname, "src/components"), - "@pages": path.resolve(__dirname, "src/pages"), - "@hooks": path.resolve(__dirname, "src/hooks"), - "@plugins": path.resolve(__dirname, "src/plugins"), - "@services": path.resolve(__dirname, "src/services"), - "@utils": path.resolve(__dirname, "src/utils"), - "@api": path.resolve(__dirname, "src/api"), - }, - }, + plugins: [ + { + plugin: CracoAliasPlugin, + options: {alias: aliasMap } + } + ], }; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 9ef92a0..1dd2134 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,9 @@ "rest-hooks": "^6.3.9", "typescript": "^4.7.4", "web-vitals": "^2.1.4" + }, + "devDependencies": { + "react-app-rewire-alias": "^1.1.7" } }, "node_modules/@adobe/css-tools": { @@ -109,28 +112,28 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz", - "integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.13.tgz", + "integrity": "sha512-5yUzC5LqyTFp2HLmDoxGQelcdYgSpP9xsnMWBphAscOdFrHSAVbLNzWiy32sVNDqJRDiJK6klfDnAgu6PAGSHw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.10.tgz", - "integrity": "sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.13.tgz", + "integrity": "sha512-ZisbOvRRusFktksHSG6pjj1CSvkPkcZq/KHD45LAkVP/oiHJkNBZWfpvlLmX8OtHDG8IuzsFlVRWo08w7Qxn0A==", "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.10", + "@babel/generator": "^7.18.13", "@babel/helper-compilation-targets": "^7.18.9", "@babel/helper-module-transforms": "^7.18.9", "@babel/helpers": "^7.18.9", - "@babel/parser": "^7.18.10", + "@babel/parser": "^7.18.13", "@babel/template": "^7.18.10", - "@babel/traverse": "^7.18.10", - "@babel/types": "^7.18.10", + "@babel/traverse": "^7.18.13", + "@babel/types": "^7.18.13", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -207,11 +210,11 @@ } }, "node_modules/@babel/generator": { - "version": "7.18.12", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.12.tgz", - "integrity": "sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.13.tgz", + "integrity": "sha512-CkPg8ySSPuHTYPJYo7IRALdqyjM9HCbt/3uOBEFbzyGVP6Mn8bwFPB0jX6982JVNBlYzM1nnPkfjuXSOPtQeEQ==", "dependencies": { - "@babel/types": "^7.18.10", + "@babel/types": "^7.18.13", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, @@ -281,9 +284,9 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.9.tgz", - "integrity": "sha512-WvypNAYaVh23QcjpMR24CwZY2Nz6hqdOcFdPbNpV56hL5H6KiFheO7Xm1aPdlLQ7d5emYZX7VZwPp9x3z+2opw==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.13.tgz", + "integrity": "sha512-hDvXp+QYxSRL+23mpAlSGxHMDyIGChm0/AwTfTAAK5Ufe40nCsyNdaYCGuK91phn/fVu9kqayImRDkvNAgdrsA==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-environment-visitor": "^7.18.9", @@ -570,9 +573,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.18.11", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.11.tgz", - "integrity": "sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.13.tgz", + "integrity": "sha512-dgXcIfMuQ0kgzLB2b9tRZs7TTFFaGM2AbtA4fJgUUYukzGH4jwsS7hzQHEGs67jdehpm22vkgKwvbU+aEflgwg==", "bin": { "parser": "bin/babel-parser.js" }, @@ -1211,9 +1214,9 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.9.tgz", - "integrity": "sha512-p5VCYNddPLkZTq4XymQIaIfZNJwT9YsjkPOhkVEqt6QIpQFZVM9IltqqYpOEkJoN1DPznmxUDyZ5CTZs/ZCuHA==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz", + "integrity": "sha512-TodpQ29XekIsex2A+YJPj5ax2plkGa8YYY6mFjCohk/IG9IY42Rtuj1FuDeemfg2ipxIFLzPeA83SIBnlhSIow==", "dependencies": { "@babel/helper-plugin-utils": "^7.18.9" }, @@ -1909,18 +1912,18 @@ } }, "node_modules/@babel/traverse": { - "version": "7.18.11", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.11.tgz", - "integrity": "sha512-TG9PiM2R/cWCAy6BPJKeHzNbu4lPzOSZpeMfeNErskGpTJx6trEvFaVCbDvpcxwy49BKWmEPwiW8mrysNiDvIQ==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.13.tgz", + "integrity": "sha512-N6kt9X1jRMLPxxxPYWi7tgvJRH/rtoU+dbKAPDM44RFHiMH8igdsaSBgFeskhSl/kLWLDUvIh1RXCrTmg0/zvA==", "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.10", + "@babel/generator": "^7.18.13", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.18.9", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.18.11", - "@babel/types": "^7.18.10", + "@babel/parser": "^7.18.13", + "@babel/types": "^7.18.13", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -1929,9 +1932,9 @@ } }, "node_modules/@babel/types": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz", - "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.13.tgz", + "integrity": "sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ==", "dependencies": { "@babel/helper-string-parser": "^7.18.10", "@babel/helper-validator-identifier": "^7.18.6", @@ -2082,6 +2085,24 @@ "postcss": "^8.2" } }, + "node_modules/@csstools/postcss-nested-calc": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-1.0.0.tgz", + "integrity": "sha512-JCsQsw1wjYwv1bJmgjKSoZNvf7R6+wuHDAbi5f/7MbFhl2d/+v+TvBTU4BJH3G1X1H87dHl0mh6TfYogbT/dJQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, "node_modules/@csstools/postcss-normalize-display-values": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-1.0.1.tgz", @@ -2151,6 +2172,24 @@ "postcss": "^8.2" } }, + "node_modules/@csstools/postcss-text-decoration-shorthand": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-1.0.0.tgz", + "integrity": "sha512-c1XwKJ2eMIWrzQenN0XbcfzckOLLJiczqy+YvfGmzoVXd7pT9FfObiSEfzs84bpE/VqfpEuAZ9tCRbZkZxxbdw==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, "node_modules/@csstools/postcss-trigonometric-functions": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-1.0.2.tgz", @@ -2209,13 +2248,13 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", - "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.1.tgz", + "integrity": "sha512-OhSY22oQQdw3zgPOOwdoj01l/Dzl1Z+xyUP33tkSN+aqyEhymJCcPHyXt+ylW8FSe0TfRC2VG+ROQOapD0aZSQ==", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.3.2", + "espree": "^9.4.0", "globals": "^13.15.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -2225,6 +2264,9 @@ }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/@eslint/eslintrc/node_modules/argparse": { @@ -2290,6 +2332,18 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@humanwhocodes/object-schema": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", @@ -2553,48 +2607,6 @@ "node": ">=8" } }, - "node_modules/@jest/core/node_modules/jest-config": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", - "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", - "dependencies": { - "@babel/core": "^7.8.0", - "@jest/test-sequencer": "^27.5.1", - "@jest/types": "^27.5.1", - "babel-jest": "^27.5.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.1", - "graceful-fs": "^4.2.9", - "jest-circus": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-jasmine2": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "ts-node": { - "optional": true - } - } - }, "node_modules/@jest/core/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -3056,9 +3068,9 @@ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", - "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -3292,9 +3304,9 @@ "integrity": "sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA==" }, "node_modules/@sinclair/typebox": { - "version": "0.24.27", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.27.tgz", - "integrity": "sha512-K7C7IlQ3zLePEZleUN21ceBA2aLcMnLHTLph8QWk1JK37L90obdpY+QGY8bXMKxf1ht1Z0MNewvXxWv0oGDYFg==" + "version": "0.24.28", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.28.tgz", + "integrity": "sha512-dgJd3HLOkLmz4Bw50eZx/zJwtBq65nms3N9VBYu5LTjJ883oBFkTyXRlCB/ZGGwqYpJJHA5zW2Ibhl5ngITfow==" }, "node_modules/@sinonjs/commons": { "version": "1.8.3", @@ -3546,20 +3558,20 @@ } }, "node_modules/@tanstack/query-core": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.0.10.tgz", - "integrity": "sha512-9LsABpZXkWZHi4P1ozRETEDXQocLAxVzQaIhganxbNuz/uA3PsCAJxJTiQrknG5htLMzOF5MqM9G10e6DCxV1A==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", + "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" } }, "node_modules/@tanstack/react-query": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.0.10.tgz", - "integrity": "sha512-Wn5QhZUE5wvr6rGClV7KeQIUsdTmYR9mgmMZen7DSRWauHW2UTynFg3Kkf6pw+XlxxOLsyLWwz/Q6q1lSpM3TQ==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.2.3.tgz", + "integrity": "sha512-JLaMOxoJTkiAu7QpevRCt2uI/0vd3E8K/rSlCuRgWlcW5DeJDFpDS5kfzmLO5MOcD97fgsJRrDbxDORxR1FdJA==", "dependencies": { - "@tanstack/query-core": "^4.0.0-beta.1", + "@tanstack/query-core": "4.2.3", "@types/use-sync-external-store": "^0.0.3", "use-sync-external-store": "^1.2.0" }, @@ -3582,9 +3594,9 @@ } }, "node_modules/@tanstack/react-query-devtools": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-4.0.10.tgz", - "integrity": "sha512-3J7LLYQjfjTI0DbPo0bA+M3l4kdvYSWAqihpeG1u93WVyZj0OEFviUv+4cK7+k2AVgQJAPMZ5xvtewKxOOFVrw==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-4.2.3.tgz", + "integrity": "sha512-0PH8n824BnFyMrtv7q5uLS0b7jYg2tDH8vU4etkSYzV1uL4RJjiqMh7Gyi8qhYCwM+khlrkRYlNZvE0cxlp3SQ==", "dependencies": { "@tanstack/match-sorter-utils": "^8.0.0-alpha.82", "@types/use-sync-external-store": "^0.0.3", @@ -3593,6 +3605,11 @@ "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "@tanstack/react-query": "4.2.3", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, "node_modules/@testing-library/dom": { @@ -3628,9 +3645,9 @@ } }, "node_modules/@testing-library/dom/node_modules/aria-query": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.0.tgz", - "integrity": "sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.2.tgz", + "integrity": "sha512-eigU3vhqSO+Z8BKDnVLN/ompjhf3pYzecKXz8+whRy+9gZu8n1TCGfwzQUUPnqdHl9ax1Hr9031orZ+UOEYr7Q==", "engines": { "node": ">=6.0" } @@ -3721,9 +3738,9 @@ } }, "node_modules/@testing-library/jest-dom/node_modules/aria-query": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.0.tgz", - "integrity": "sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.2.tgz", + "integrity": "sha512-eigU3vhqSO+Z8BKDnVLN/ompjhf3pYzecKXz8+whRy+9gZu8n1TCGfwzQUUPnqdHl9ax1Hr9031orZ+UOEYr7Q==", "engines": { "node": ">=6.0" } @@ -3900,9 +3917,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.4.5", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.5.tgz", - "integrity": "sha512-dhsC09y1gpJWnK+Ff4SGvCuSnk9DaU0BJZSzOwa6GVSg65XtTugLBITDAAzRU5duGBoXBHpdR/9jHGxJjNflJQ==", + "version": "8.4.6", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.6.tgz", + "integrity": "sha512-/fqTbjxyFUaYNO7VcW5g+4npmqVACz1bB7RTHYuLj+PRjw9hrCwrUXVQFpChUS0JsyEFvMZ7U/PfmvWgxJhI9g==", "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -4010,9 +4027,9 @@ "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" }, "node_modules/@types/node": { - "version": "16.11.47", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.47.tgz", - "integrity": "sha512-fpP+jk2zJ4VW66+wAMFoBJlx1bxmBKx4DUFf68UHgdGCOuyUTDlLWqsaNPJh7xhNDykyJ9eIzAygilP/4WoN8g==" + "version": "16.11.56", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.56.tgz", + "integrity": "sha512-aFcUkv7EddxxOa/9f74DINReQ/celqH8DiB3fRYgVDM2Xm5QJL8sl80QKuAnGvwAsMn+H3IFA6WCrQh1CY7m1A==" }, "node_modules/@types/parse-json": { "version": "4.0.0", @@ -4207,13 +4224,13 @@ "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.33.0.tgz", - "integrity": "sha512-jHvZNSW2WZ31OPJ3enhLrEKvAZNyAFWZ6rx9tUwaessTc4sx9KmgMNhVcqVAl1ETnT5rU5fpXTLmY9YvC1DCNg==", + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.35.1.tgz", + "integrity": "sha512-RBZZXZlI4XCY4Wzgy64vB+0slT9+yAPQRjj/HSaRwUot33xbDjF1oN9BLwOLTewoOI0jothIltZRe9uJCHf8gg==", "dependencies": { - "@typescript-eslint/scope-manager": "5.33.0", - "@typescript-eslint/type-utils": "5.33.0", - "@typescript-eslint/utils": "5.33.0", + "@typescript-eslint/scope-manager": "5.35.1", + "@typescript-eslint/type-utils": "5.35.1", + "@typescript-eslint/utils": "5.35.1", "debug": "^4.3.4", "functional-red-black-tree": "^1.0.1", "ignore": "^5.2.0", @@ -4239,11 +4256,11 @@ } }, "node_modules/@typescript-eslint/experimental-utils": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.33.0.tgz", - "integrity": "sha512-NvRsNe+T90QrSVlgdV9/U8/chfqGmShvKUE7hWZTAUUCF6hZty/R+eMPVGldKcUDq7uRQaK6+V8gv5OwVDqC+g==", + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.35.1.tgz", + "integrity": "sha512-nF7JD9alMkhEx50QYDUdP8koeHtldnm7EfZkr68ikkc87ffFBIPkH3dqoWyOeQeIiJicB0uHzpMXKR6PP+1Jbg==", "dependencies": { - "@typescript-eslint/utils": "5.33.0" + "@typescript-eslint/utils": "5.35.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -4257,13 +4274,13 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.33.0.tgz", - "integrity": "sha512-cgM5cJrWmrDV2KpvlcSkelTBASAs1mgqq+IUGKJvFxWrapHpaRy5EXPQz9YaKF3nZ8KY18ILTiVpUtbIac86/w==", + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.35.1.tgz", + "integrity": "sha512-XL2TBTSrh3yWAsMYpKseBYTVpvudNf69rPOWXWVBI08My2JVT5jR66eTt4IgQFHA/giiKJW5dUD4x/ZviCKyGg==", "dependencies": { - "@typescript-eslint/scope-manager": "5.33.0", - "@typescript-eslint/types": "5.33.0", - "@typescript-eslint/typescript-estree": "5.33.0", + "@typescript-eslint/scope-manager": "5.35.1", + "@typescript-eslint/types": "5.35.1", + "@typescript-eslint/typescript-estree": "5.35.1", "debug": "^4.3.4" }, "engines": { @@ -4283,12 +4300,12 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.33.0.tgz", - "integrity": "sha512-/Jta8yMNpXYpRDl8EwF/M8It2A9sFJTubDo0ATZefGXmOqlaBffEw0ZbkbQ7TNDK6q55NPHFshGBPAZvZkE8Pw==", + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.35.1.tgz", + "integrity": "sha512-kCYRSAzIW9ByEIzmzGHE50NGAvAP3wFTaZevgWva7GpquDyFPFcmvVkFJGWJJktg/hLwmys/FZwqM9EKr2u24Q==", "dependencies": { - "@typescript-eslint/types": "5.33.0", - "@typescript-eslint/visitor-keys": "5.33.0" + "@typescript-eslint/types": "5.35.1", + "@typescript-eslint/visitor-keys": "5.35.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -4299,11 +4316,11 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.33.0.tgz", - "integrity": "sha512-2zB8uEn7hEH2pBeyk3NpzX1p3lF9dKrEbnXq1F7YkpZ6hlyqb2yZujqgRGqXgRBTHWIUG3NGx/WeZk224UKlIA==", + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.35.1.tgz", + "integrity": "sha512-8xT8ljvo43Mp7BiTn1vxLXkjpw8wS4oAc00hMSB4L1/jIiYbjjnc3Qp2GAUOG/v8zsNCd1qwcqfCQ0BuishHkw==", "dependencies": { - "@typescript-eslint/utils": "5.33.0", + "@typescript-eslint/utils": "5.35.1", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -4324,9 +4341,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.33.0.tgz", - "integrity": "sha512-nIMt96JngB4MYFYXpZ/3ZNU4GWPNdBbcB5w2rDOCpXOVUkhtNlG2mmm8uXhubhidRZdwMaMBap7Uk8SZMU/ppw==", + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.35.1.tgz", + "integrity": "sha512-FDaujtsH07VHzG0gQ6NDkVVhi1+rhq0qEvzHdJAQjysN+LHDCKDKCBRlZFFE0ec0jKxiv0hN63SNfExy0KrbQQ==", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -4336,12 +4353,12 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.33.0.tgz", - "integrity": "sha512-tqq3MRLlggkJKJUrzM6wltk8NckKyyorCSGMq4eVkyL5sDYzJJcMgZATqmF8fLdsWrW7OjjIZ1m9v81vKcaqwQ==", + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.35.1.tgz", + "integrity": "sha512-JUqE1+VRTGyoXlDWWjm6MdfpBYVq+hixytrv1oyjYIBEOZhBCwtpp5ZSvBt4wIA1MKWlnaC2UXl2XmYGC3BoQA==", "dependencies": { - "@typescript-eslint/types": "5.33.0", - "@typescript-eslint/visitor-keys": "5.33.0", + "@typescript-eslint/types": "5.35.1", + "@typescript-eslint/visitor-keys": "5.35.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -4362,14 +4379,14 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.33.0.tgz", - "integrity": "sha512-JxOAnXt9oZjXLIiXb5ZIcZXiwVHCkqZgof0O8KPgz7C7y0HS42gi75PdPlqh1Tf109M0fyUw45Ao6JLo7S5AHw==", + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.35.1.tgz", + "integrity": "sha512-v6F8JNXgeBWI4pzZn36hT2HXXzoBBBJuOYvoQiaQaEEjdi5STzux3Yj8v7ODIpx36i/5s8TdzuQ54TPc5AITQQ==", "dependencies": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.33.0", - "@typescript-eslint/types": "5.33.0", - "@typescript-eslint/typescript-estree": "5.33.0", + "@typescript-eslint/scope-manager": "5.35.1", + "@typescript-eslint/types": "5.35.1", + "@typescript-eslint/typescript-estree": "5.35.1", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" }, @@ -4405,11 +4422,11 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.33.0.tgz", - "integrity": "sha512-/XsqCzD4t+Y9p5wd9HZiptuGKBlaZO5showwqODii5C0nZawxWLF+Q6k5wYHBrQv96h6GYKyqqMHCSTqta8Kiw==", + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.35.1.tgz", + "integrity": "sha512-cEB1DvBVo1bxbW/S5axbGPE6b7FIMAbo3w+AGq6zNDA7+NYJOIkKj/sInfTv4edxd4PxJSgdN4t6/pbvgA+n5g==", "dependencies": { - "@typescript-eslint/types": "5.33.0", + "@typescript-eslint/types": "5.35.1", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -4708,14 +4725,6 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-globals/node_modules/acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/acorn-import-assertions": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", @@ -4753,7 +4762,7 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-node/node_modules/acorn-walk": { + "node_modules/acorn-walk": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", @@ -4904,9 +4913,9 @@ } }, "node_modules/antd": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/antd/-/antd-4.22.4.tgz", - "integrity": "sha512-u7l68PhSJMxyZmCNw+jwaeurSAaE+bU+lB0SPRHLfOFJR6xRudntvRoQdiEFOD5FZ3eeqz4lYQ3RZZRIarmceg==", + "version": "4.22.8", + "resolved": "https://registry.npmjs.org/antd/-/antd-4.22.8.tgz", + "integrity": "sha512-mqHuCg9itZX+z6wk+mvRBcfz/U9iiIXS4LoNkyo8X/UBgdN8CoetFmrdvA1UQy1BuWa0/n62LiS1LatdvoTuHw==", "dependencies": { "@ant-design/colors": "^6.0.0", "@ant-design/icons": "^4.7.0", @@ -4922,14 +4931,14 @@ "rc-checkbox": "~2.3.0", "rc-collapse": "~3.3.0", "rc-dialog": "~8.9.0", - "rc-drawer": "~5.1.0-alpha.1", + "rc-drawer": "~5.1.0", "rc-dropdown": "~4.0.0", "rc-field-form": "~1.27.0", "rc-image": "~5.7.0", "rc-input": "~0.0.1-alpha.5", "rc-input-number": "~7.3.5", "rc-mentions": "~1.9.1", - "rc-menu": "~9.6.0", + "rc-menu": "~9.6.3", "rc-motion": "^2.6.1", "rc-notification": "~4.6.0", "rc-pagination": "~3.1.17", @@ -4979,6 +4988,11 @@ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -6087,9 +6101,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001375", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001375.tgz", - "integrity": "sha512-kWIMkNzLYxSvnjy0hL8w1NOaWNr2rn39RTAVyIwcw8juu60bZDWiF1/loOYANzjtJmy6qPgNmn38ro5Pygagdw==", + "version": "1.0.30001383", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001383.tgz", + "integrity": "sha512-swMpEoTp5vDoGBZsYZX7L7nXHe6dsHxi9o6/LKf/f0LukVtnrxly5GVb/fWdCDTqi/yw6Km6tiJ0pmBacm0gbg==", "funding": [ { "type": "opencollective", @@ -6642,9 +6656,9 @@ } }, "node_modules/core-js": { - "version": "3.24.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.24.1.tgz", - "integrity": "sha512-0QTBSYSUZ6Gq21utGzkfITDylE8jWC9Ne1D2MrhvlsZBI1x39OdDIVbzSqtgMndIy6BlHxBXpMGqzZmnztg2rg==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", "hasInstallScript": true, "funding": { "type": "opencollective", @@ -6652,9 +6666,9 @@ } }, "node_modules/core-js-compat": { - "version": "3.24.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.24.1.tgz", - "integrity": "sha512-XhdNAGeRnTpp8xbD+sR/HFDK9CbeeeqXT6TuofXh3urqEevzkWmLRgrVoykodsw8okqo2pu1BOmuCKrHx63zdw==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.25.0.tgz", + "integrity": "sha512-extKQM0g8/3GjFx9US12FAgx8KJawB7RCQ5y8ipYLbmfzEzmFRWdDjIlxDx82g7ygcNG85qMVUSRyABouELdow==", "dependencies": { "browserslist": "^4.21.3", "semver": "7.0.0" @@ -6673,9 +6687,9 @@ } }, "node_modules/core-js-pure": { - "version": "3.24.1", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.24.1.tgz", - "integrity": "sha512-r1nJk41QLLPyozHUUPmILCEMtMw24NG4oWK6RbsDdjzQgg9ZvrUsPBj1MnG0wXXp1DCDU6j+wUvEmBSrtRbLXg==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.25.0.tgz", + "integrity": "sha512-IeHpLwk3uoci37yoI2Laty59+YqH9x5uR65/yiA0ARAJrTrN4YU0rmauLWfvqOuk77SlNJXj2rM6oT/dBD87+A==", "hasInstallScript": true, "funding": { "type": "opencollective", @@ -7648,9 +7662,9 @@ "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==" }, "node_modules/cssdb": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-6.6.3.tgz", - "integrity": "sha512-7GDvDSmE+20+WcSMhP17Q1EVWUrLlbxxpMDqG731n8P99JhnQZHR9YvtjPvEHfjFUjvQJvdpKCjlKOX+xe4UVA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.0.1.tgz", + "integrity": "sha512-pT3nzyGM78poCKLAEy2zWIVX2hikq6dIrjuZzLV98MumBg+xMTNYfHx7paUlfiRTgg91O/vR889CIf+qiv79Rw==", "funding": { "type": "opencollective", "url": "https://opencollective.com/csstools" @@ -7668,9 +7682,9 @@ } }, "node_modules/cssnano": { - "version": "5.1.12", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.12.tgz", - "integrity": "sha512-TgvArbEZu0lk/dvg2ja+B7kYoD7BBCmn3+k58xD0qjrGHsFzXY/wKTo9M5egcUCabPol05e/PVoIu79s2JN4WQ==", + "version": "5.1.13", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.13.tgz", + "integrity": "sha512-S2SL2ekdEz6w6a2epXn4CmMKU4K3KpcyXLKfAYc9UQQqJRkD/2eLUG0vJ3Db/9OvO5GuAdgXw3pFbR6abqghDQ==", "dependencies": { "cssnano-preset-default": "^5.2.12", "lilconfig": "^2.0.3", @@ -7826,9 +7840,9 @@ } }, "node_modules/date-fns": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.1.tgz", - "integrity": "sha512-dlLD5rKaKxpFdnjrs+5azHDFOPEu4ANy/LTh04A1DTzMM7qoajmKCBc8pkKRFT41CNzw+4gQh79X5C+Jq27HAw==", + "version": "2.29.2", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.2.tgz", + "integrity": "sha512-0VNbwmWJDS/G3ySwFSJA3ayhbURMTJLtwM2DTxf9CWondCnh6DTNlO9JgRSq6ibf4eD0lfMJNBxUdEAHHix+bA==", "engines": { "node": ">=0.11" }, @@ -7838,9 +7852,9 @@ } }, "node_modules/dayjs": { - "version": "1.11.4", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.4.tgz", - "integrity": "sha512-Zj/lPM5hOvQ1Bf7uAvewDaUcsJoI6JmNqmHhHl3nyumwe0XHwt8sWdOVAPACJzCebL8gQCi+K49w7iKWnGwX9g==" + "version": "1.11.5", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.5.tgz", + "integrity": "sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA==" }, "node_modules/debug": { "version": "4.3.4", @@ -7859,9 +7873,9 @@ } }, "node_modules/decimal.js": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", - "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==" + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.0.tgz", + "integrity": "sha512-Nv6ENEzyPQ6AItkGwLE2PGKinZZ9g59vSh2BeH6NqPu0OTKZ5ruJsVqh/orbAnqXc9pBbgXAIrc2EyaCj8NpGg==" }, "node_modules/decode-uri-component": { "version": "0.2.0", @@ -8280,9 +8294,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.213", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.213.tgz", - "integrity": "sha512-+3DbGHGOCHTVB/Ms63bGqbyC1b8y7Fk86+7ltssB8NQrZtSCvZG6eooSl9U2Q0yw++fL2DpHKOdTU0NVEkFObg==" + "version": "1.4.233", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.233.tgz", + "integrity": "sha512-ejwIKXTg1wqbmkcRJh9Ur3hFGHFDZDw1POzdsVrB2WZjgRuRMHIQQKNpe64N/qh3ZtH2otEoRoS+s6arAAuAAw==" }, "node_modules/elliptic": { "version": "6.5.4", @@ -8559,13 +8573,14 @@ } }, "node_modules/eslint": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.21.0.tgz", - "integrity": "sha512-/XJ1+Qurf1T9G2M5IHrsjp+xrGT73RZf23xA1z5wB1ZzzEAWSZKvRwhWxTFp1rvkvCfwcvAUNAP31bhKTTGfDA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.23.0.tgz", + "integrity": "sha512-pBG/XOn0MsJcKcTRLr27S5HpzQo4kLr+HjLQIyK4EiCsijDl/TB+h5uEuJU6bQ8Edvwz1XWOjpaP2qgnXGpTcA==", "dependencies": { - "@eslint/eslintrc": "^1.3.0", + "@eslint/eslintrc": "^1.3.1", "@humanwhocodes/config-array": "^0.10.4", "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", + "@humanwhocodes/module-importer": "^1.0.1", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -8575,7 +8590,7 @@ "eslint-scope": "^7.1.1", "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.3", + "espree": "^9.4.0", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -8600,8 +8615,7 @@ "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "text-table": "^0.2.0" }, "bin": { "eslint": "bin/eslint.js" @@ -8658,15 +8672,19 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz", - "integrity": "sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==", + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", + "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", "dependencies": { - "debug": "^3.2.7", - "find-up": "^2.1.0" + "debug": "^3.2.7" }, "engines": { "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, "node_modules/eslint-module-utils/node_modules/debug": { @@ -8677,67 +8695,6 @@ "ms": "^2.1.1" } }, - "node_modules/eslint-module-utils/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "engines": { - "node": ">=4" - } - }, "node_modules/eslint-plugin-flowtype": { "version": "8.0.3", "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz", @@ -8863,9 +8820,9 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.30.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.30.1.tgz", - "integrity": "sha512-NbEvI9jtqO46yJA3wcRF9Mo0lF9T/jhdHqhCHXiXtD+Zcb98812wvokjWpU7Q4QH5edo6dmqrukxVvWWXHlsUg==", + "version": "7.31.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.1.tgz", + "integrity": "sha512-j4/2xWqt/R7AZzG8CakGHA6Xa/u7iR8Q3xCxY+AUghdT92bnIDOBEefV456OeH0QvBcroVc0eyvrrLSyQGYIfg==", "dependencies": { "array-includes": "^3.1.5", "array.prototype.flatmap": "^1.3.0", @@ -9219,9 +9176,9 @@ } }, "node_modules/espree": { - "version": "9.3.3", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.3.tgz", - "integrity": "sha512-ORs1Rt/uQTqUKjDdGCyrtYxbazf5umATSf/K4qxjmZHORR6HJk+2s/2Pqe+Kk49HHINC/xNIrGfgh8sZcll0ng==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", + "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", "dependencies": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", @@ -9855,9 +9812,9 @@ } }, "node_modules/flatted": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz", - "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==" + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" }, "node_modules/flush-write-stream": { "version": "1.1.1", @@ -11854,7 +11811,18 @@ "node": ">=8" } }, - "node_modules/jest-cli/node_modules/jest-config": { + "node_modules/jest-cli/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", @@ -11896,7 +11864,60 @@ } } }, - "node_modules/jest-cli/node_modules/supports-color": { + "node_modules/jest-config/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-config/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/jest-config/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -14675,9 +14696,9 @@ } }, "node_modules/object.assign": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.3.tgz", - "integrity": "sha512-ZFJnX3zltyjcYJL0RoCJuzb+11zWGyaDbjgxZbdV7rFEcHQuYxrZqhow67aA7xpes6LhojyFDaBKAFfogQrikA==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -15725,6 +15746,34 @@ "postcss": "^8.2" } }, + "node_modules/postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dependencies": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, "node_modules/postcss-loader": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", @@ -16172,56 +16221,58 @@ } }, "node_modules/postcss-preset-env": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.7.2.tgz", - "integrity": "sha512-1q0ih7EDsZmCb/FMDRvosna7Gsbdx8CvYO5hYT120hcp2ZAuOHpSzibujZ4JpIUcAC02PG6b+eftxqjTFh5BNA==", - "dependencies": { - "@csstools/postcss-cascade-layers": "^1.0.4", - "@csstools/postcss-color-function": "^1.1.0", - "@csstools/postcss-font-format-keywords": "^1.0.0", - "@csstools/postcss-hwb-function": "^1.0.1", - "@csstools/postcss-ic-unit": "^1.0.0", - "@csstools/postcss-is-pseudo-class": "^2.0.6", - "@csstools/postcss-normalize-display-values": "^1.0.0", - "@csstools/postcss-oklab-function": "^1.1.0", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.8.0.tgz", + "integrity": "sha512-leqiqLOellpLKfbHkD06E04P6d9ZQ24mat6hu4NSqun7WG0UhspHR5Myiv/510qouCjoo4+YJtNOqg5xHaFnCA==", + "dependencies": { + "@csstools/postcss-cascade-layers": "^1.0.5", + "@csstools/postcss-color-function": "^1.1.1", + "@csstools/postcss-font-format-keywords": "^1.0.1", + "@csstools/postcss-hwb-function": "^1.0.2", + "@csstools/postcss-ic-unit": "^1.0.1", + "@csstools/postcss-is-pseudo-class": "^2.0.7", + "@csstools/postcss-nested-calc": "^1.0.0", + "@csstools/postcss-normalize-display-values": "^1.0.1", + "@csstools/postcss-oklab-function": "^1.1.1", "@csstools/postcss-progressive-custom-properties": "^1.3.0", - "@csstools/postcss-stepped-value-functions": "^1.0.0", - "@csstools/postcss-trigonometric-functions": "^1.0.1", - "@csstools/postcss-unset-value": "^1.0.1", - "autoprefixer": "^10.4.7", - "browserslist": "^4.21.0", + "@csstools/postcss-stepped-value-functions": "^1.0.1", + "@csstools/postcss-text-decoration-shorthand": "^1.0.0", + "@csstools/postcss-trigonometric-functions": "^1.0.2", + "@csstools/postcss-unset-value": "^1.0.2", + "autoprefixer": "^10.4.8", + "browserslist": "^4.21.3", "css-blank-pseudo": "^3.0.3", "css-has-pseudo": "^3.0.4", "css-prefers-color-scheme": "^6.0.3", - "cssdb": "^6.6.3", - "postcss-attribute-case-insensitive": "^5.0.1", + "cssdb": "^7.0.0", + "postcss-attribute-case-insensitive": "^5.0.2", "postcss-clamp": "^4.1.0", - "postcss-color-functional-notation": "^4.2.3", + "postcss-color-functional-notation": "^4.2.4", "postcss-color-hex-alpha": "^8.0.4", - "postcss-color-rebeccapurple": "^7.1.0", + "postcss-color-rebeccapurple": "^7.1.1", "postcss-custom-media": "^8.0.2", "postcss-custom-properties": "^12.1.8", "postcss-custom-selectors": "^6.0.3", - "postcss-dir-pseudo-class": "^6.0.4", - "postcss-double-position-gradients": "^3.1.1", + "postcss-dir-pseudo-class": "^6.0.5", + "postcss-double-position-gradients": "^3.1.2", "postcss-env-function": "^4.0.6", "postcss-focus-visible": "^6.0.4", "postcss-focus-within": "^5.0.4", "postcss-font-variant": "^5.0.0", - "postcss-gap-properties": "^3.0.3", - "postcss-image-set-function": "^4.0.6", + "postcss-gap-properties": "^3.0.5", + "postcss-image-set-function": "^4.0.7", "postcss-initial": "^4.0.1", - "postcss-lab-function": "^4.2.0", + "postcss-lab-function": "^4.2.1", "postcss-logical": "^5.0.4", "postcss-media-minmax": "^5.0.0", - "postcss-nesting": "^10.1.9", + "postcss-nesting": "^10.1.10", "postcss-opacity-percentage": "^1.1.2", - "postcss-overflow-shorthand": "^3.0.3", + "postcss-overflow-shorthand": "^3.0.4", "postcss-page-break": "^3.0.4", - "postcss-place": "^7.0.4", - "postcss-pseudo-class-any-link": "^7.1.5", + "postcss-place": "^7.0.5", + "postcss-pseudo-class-any-link": "^7.1.6", "postcss-replace-overflow-wrap": "^4.0.0", - "postcss-selector-not": "^6.0.0", + "postcss-selector-not": "^6.0.1", "postcss-value-parser": "^4.2.0" }, "engines": { @@ -16636,6 +16687,11 @@ "node": ">=0.4.x" } }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -16750,9 +16806,9 @@ } }, "node_modules/rc-cascader": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.6.1.tgz", - "integrity": "sha512-+GmN2Z0IybKT45t0Z94jkjmsOHGxAliobR2tzt05/Gw0AKBYLHX5bdvsVXR7abPnarYyYzZ/cWe8CoFgDjAFNw==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.6.2.tgz", + "integrity": "sha512-sf2otpazlROTzkD3nZVfIzXmfBLiEOBTXA5wxozGXBpS902McDpvF0bdcYBu5hN+rviEAm6Mh9cLXNQ1Ty8wKQ==", "dependencies": { "@babel/runtime": "^7.12.5", "array-tree-filter": "^2.1.0", @@ -16901,9 +16957,9 @@ } }, "node_modules/rc-mentions": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-1.9.1.tgz", - "integrity": "sha512-6VBaEkJjYdGGxAygQvE2NaIegAzLJSDodgzpoV+vonUUCZ4A/d8izVlc2JqCYa0Yi15HiDcWyfRgJYI7OKTILg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-1.9.2.tgz", + "integrity": "sha512-uxb/lzNnEGmvraKWNGE6KXMVXvt8RQv9XW8R0Dqi3hYsyPiAZeHRCHQKdLARuk5YBhFhZ6ga55D/8XuY367g3g==", "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.6", @@ -16918,9 +16974,9 @@ } }, "node_modules/rc-menu": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.6.2.tgz", - "integrity": "sha512-sSobfm30OAw6XfVaj+rEkBfalLxbZ3uOsB876MCG6NmwXQGSKRv+arTBnJnJqAmCGh2dMyb/Jf9kTCMpII6RTg==", + "version": "9.6.3", + "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.6.3.tgz", + "integrity": "sha512-KY9QilKWgkJZ0JSpOBgIpQF2wMRRodRxpIMYyIJ3Nd5N6xfVLOxXCxevHcBplt+Ez7MhUF+I03MuAKqWQJLZgw==", "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "2.x", @@ -17237,9 +17293,9 @@ } }, "node_modules/rc-tree-select": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.4.0.tgz", - "integrity": "sha512-reRbOqC7Ic/nQocJAJeCl4n6nJUY3NoqiwRXKvhjgZJU7NGr9vIccXEsY+Lghkw5UMpPoxGsIJB0jiAvM18XYA==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.4.1.tgz", + "integrity": "sha512-xhXnKP8Stu2Q7wTcjJaSzSOLd4wmFtUZOwmy1cioaWyPbpiKlYdnALXA/9U49HOaV3KFXdRHE9Yi0KYED7yOAQ==", "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "2.x", @@ -17348,6 +17404,41 @@ "node": ">=14" } }, + "node_modules/react-app-rewire-alias": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/react-app-rewire-alias/-/react-app-rewire-alias-1.1.7.tgz", + "integrity": "sha512-vn4xU3E/wzh2/fGxda9ZQ6CtW2XdZB/WxAgNOdNPyUcX3hA3mh+kCRGwo19gSjzeTPpoZQwZRblHabLr6mwOTw==", + "dev": true, + "peerDependencies": { + "react-app-rewired": "1 || ^2" + } + }, + "node_modules/react-app-rewired": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-app-rewired/-/react-app-rewired-2.2.1.tgz", + "integrity": "sha512-uFQWTErXeLDrMzOJHKp0h8P1z0LV9HzPGsJ6adOtGlA/B9WfT6Shh4j2tLTTGlXOfiVx6w6iWpp7SOC5pvk+gA==", + "dev": true, + "peer": true, + "dependencies": { + "semver": "^5.6.0" + }, + "bin": { + "react-app-rewired": "bin/index.js" + }, + "peerDependencies": { + "react-scripts": ">=2.1.3" + } + }, + "node_modules/react-app-rewired/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "peer": true, + "bin": { + "semver": "bin/semver" + } + }, "node_modules/react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -17656,9 +17747,9 @@ } }, "node_modules/recoil": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/recoil/-/recoil-0.7.4.tgz", - "integrity": "sha512-sCXvQGMfSprkNU4ZRkJV4B0qFQSURJMgsICqY1952WRlg66NMwYqi6n67vhnhn0qw4zHU1gHXJuMvRDaiRNFZw==", + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/recoil/-/recoil-0.7.5.tgz", + "integrity": "sha512-GVShsj5+M/2GULWBs5WBJGcsNis/d3YvDiaKjYh3mLKXftjtmk9kfaQ8jwjoIXySCwn8/RhgJ4Sshwgzj2UpFA==", "dependencies": { "hamt_plus": "1.0.2" }, @@ -18070,9 +18161,9 @@ } }, "node_modules/rollup": { - "version": "2.77.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.77.2.tgz", - "integrity": "sha512-m/4YzYgLcpMQbxX3NmAqDvwLATZzxt8bIegO78FZLl+lAgKJBd1DRAOeEiZcKOIOPjxE6ewHWHNgGEalFXuz1g==", + "version": "2.78.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", + "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", "bin": { "rollup": "dist/bin/rollup" }, @@ -18859,9 +18950,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", - "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==" + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", + "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==" }, "node_modules/spdy": { "version": "4.0.2", @@ -19529,44 +19620,11 @@ "postcss": "^8.0.9" } }, - "node_modules/tailwindcss/node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" - }, "node_modules/tailwindcss/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "node_modules/tailwindcss/node_modules/postcss-load-config": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", - "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", - "dependencies": { - "lilconfig": "^2.0.5", - "yaml": "^1.10.2" - }, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -19627,9 +19685,9 @@ } }, "node_modules/terser": { - "version": "5.14.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz", - "integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", + "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", "dependencies": { "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", @@ -19644,15 +19702,15 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.3.tgz", - "integrity": "sha512-Fx60G5HNYknNTNQnzQ1VePRuu89ZVYWfjRAeT5rITuCY/1b08s49e5kSQwHDirKZWuoKOBRFS98EUUoZ9kLEwQ==", + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.5.tgz", + "integrity": "sha512-AOEDLDxD2zylUGf/wxHxklEkOe2/r+seuyOWujejFrIxHf11brA1/dWQNIgXa1c6/Wkxgu7zvv0JhOWfc2ELEA==", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.7", + "@jridgewell/trace-mapping": "^0.3.14", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.0", - "terser": "^5.7.2" + "terser": "^5.14.1" }, "engines": { "node": ">= 10.13.0" @@ -19830,22 +19888,23 @@ } }, "node_modules/tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz", + "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==", "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", - "universalify": "^0.1.2" + "universalify": "^0.2.0", + "url-parse": "^1.5.3" }, "engines": { "node": ">=6" } }, "node_modules/tough-cookie/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", "engines": { "node": ">= 4.0.0" } @@ -19981,9 +20040,9 @@ } }, "node_modules/typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz", + "integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -20213,6 +20272,15 @@ "querystring": "0.2.0" } }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "node_modules/url/node_modules/punycode": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", @@ -20287,11 +20355,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==" - }, "node_modules/v8-to-istanbul": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", @@ -21607,25 +21670,25 @@ } }, "@babel/compat-data": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz", - "integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==" + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.13.tgz", + "integrity": "sha512-5yUzC5LqyTFp2HLmDoxGQelcdYgSpP9xsnMWBphAscOdFrHSAVbLNzWiy32sVNDqJRDiJK6klfDnAgu6PAGSHw==" }, "@babel/core": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.10.tgz", - "integrity": "sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.13.tgz", + "integrity": "sha512-ZisbOvRRusFktksHSG6pjj1CSvkPkcZq/KHD45LAkVP/oiHJkNBZWfpvlLmX8OtHDG8IuzsFlVRWo08w7Qxn0A==", "requires": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.10", + "@babel/generator": "^7.18.13", "@babel/helper-compilation-targets": "^7.18.9", "@babel/helper-module-transforms": "^7.18.9", "@babel/helpers": "^7.18.9", - "@babel/parser": "^7.18.10", + "@babel/parser": "^7.18.13", "@babel/template": "^7.18.10", - "@babel/traverse": "^7.18.10", - "@babel/types": "^7.18.10", + "@babel/traverse": "^7.18.13", + "@babel/types": "^7.18.13", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -21677,11 +21740,11 @@ } }, "@babel/generator": { - "version": "7.18.12", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.12.tgz", - "integrity": "sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.13.tgz", + "integrity": "sha512-CkPg8ySSPuHTYPJYo7IRALdqyjM9HCbt/3uOBEFbzyGVP6Mn8bwFPB0jX6982JVNBlYzM1nnPkfjuXSOPtQeEQ==", "requires": { - "@babel/types": "^7.18.10", + "@babel/types": "^7.18.13", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, @@ -21734,9 +21797,9 @@ } }, "@babel/helper-create-class-features-plugin": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.9.tgz", - "integrity": "sha512-WvypNAYaVh23QcjpMR24CwZY2Nz6hqdOcFdPbNpV56hL5H6KiFheO7Xm1aPdlLQ7d5emYZX7VZwPp9x3z+2opw==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.13.tgz", + "integrity": "sha512-hDvXp+QYxSRL+23mpAlSGxHMDyIGChm0/AwTfTAAK5Ufe40nCsyNdaYCGuK91phn/fVu9kqayImRDkvNAgdrsA==", "requires": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-environment-visitor": "^7.18.9", @@ -21944,9 +22007,9 @@ } }, "@babel/parser": { - "version": "7.18.11", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.11.tgz", - "integrity": "sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==" + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.13.tgz", + "integrity": "sha512-dgXcIfMuQ0kgzLB2b9tRZs7TTFFaGM2AbtA4fJgUUYukzGH4jwsS7hzQHEGs67jdehpm22vkgKwvbU+aEflgwg==" }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.18.6", @@ -22348,9 +22411,9 @@ } }, "@babel/plugin-transform-destructuring": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.9.tgz", - "integrity": "sha512-p5VCYNddPLkZTq4XymQIaIfZNJwT9YsjkPOhkVEqt6QIpQFZVM9IltqqYpOEkJoN1DPznmxUDyZ5CTZs/ZCuHA==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz", + "integrity": "sha512-TodpQ29XekIsex2A+YJPj5ax2plkGa8YYY6mFjCohk/IG9IY42Rtuj1FuDeemfg2ipxIFLzPeA83SIBnlhSIow==", "requires": { "@babel/helper-plugin-utils": "^7.18.9" } @@ -22810,26 +22873,26 @@ } }, "@babel/traverse": { - "version": "7.18.11", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.11.tgz", - "integrity": "sha512-TG9PiM2R/cWCAy6BPJKeHzNbu4lPzOSZpeMfeNErskGpTJx6trEvFaVCbDvpcxwy49BKWmEPwiW8mrysNiDvIQ==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.13.tgz", + "integrity": "sha512-N6kt9X1jRMLPxxxPYWi7tgvJRH/rtoU+dbKAPDM44RFHiMH8igdsaSBgFeskhSl/kLWLDUvIh1RXCrTmg0/zvA==", "requires": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.10", + "@babel/generator": "^7.18.13", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.18.9", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.18.11", - "@babel/types": "^7.18.10", + "@babel/parser": "^7.18.13", + "@babel/types": "^7.18.13", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz", - "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.13.tgz", + "integrity": "sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ==", "requires": { "@babel/helper-string-parser": "^7.18.10", "@babel/helper-validator-identifier": "^7.18.6", @@ -22908,6 +22971,14 @@ "postcss-selector-parser": "^6.0.10" } }, + "@csstools/postcss-nested-calc": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-1.0.0.tgz", + "integrity": "sha512-JCsQsw1wjYwv1bJmgjKSoZNvf7R6+wuHDAbi5f/7MbFhl2d/+v+TvBTU4BJH3G1X1H87dHl0mh6TfYogbT/dJQ==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, "@csstools/postcss-normalize-display-values": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-1.0.1.tgz", @@ -22941,6 +23012,14 @@ "postcss-value-parser": "^4.2.0" } }, + "@csstools/postcss-text-decoration-shorthand": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-1.0.0.tgz", + "integrity": "sha512-c1XwKJ2eMIWrzQenN0XbcfzckOLLJiczqy+YvfGmzoVXd7pT9FfObiSEfzs84bpE/VqfpEuAZ9tCRbZkZxxbdw==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, "@csstools/postcss-trigonometric-functions": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-1.0.2.tgz", @@ -22967,13 +23046,13 @@ "integrity": "sha512-ej5oVy6lykXsvieQtqZxCOaLT+xD4+QNarq78cIYISHmZXshCvROLudpQN3lfL8G0NL7plMSSK+zlyvCaIJ4Iw==" }, "@eslint/eslintrc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", - "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.1.tgz", + "integrity": "sha512-OhSY22oQQdw3zgPOOwdoj01l/Dzl1Z+xyUP33tkSN+aqyEhymJCcPHyXt+ylW8FSe0TfRC2VG+ROQOapD0aZSQ==", "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.3.2", + "espree": "^9.4.0", "globals": "^13.15.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -23025,6 +23104,11 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz", "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==" }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==" + }, "@humanwhocodes/object-schema": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", @@ -23215,37 +23299,6 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, - "jest-config": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", - "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", - "requires": { - "@babel/core": "^7.8.0", - "@jest/test-sequencer": "^27.5.1", - "@jest/types": "^27.5.1", - "babel-jest": "^27.5.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.1", - "graceful-fs": "^4.2.9", - "jest-circus": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-jasmine2": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - } - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -23594,9 +23647,9 @@ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "@jridgewell/trace-mapping": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", - "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", "requires": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -23736,9 +23789,9 @@ "integrity": "sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA==" }, "@sinclair/typebox": { - "version": "0.24.27", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.27.tgz", - "integrity": "sha512-K7C7IlQ3zLePEZleUN21ceBA2aLcMnLHTLph8QWk1JK37L90obdpY+QGY8bXMKxf1ht1Z0MNewvXxWv0oGDYFg==" + "version": "0.24.28", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.28.tgz", + "integrity": "sha512-dgJd3HLOkLmz4Bw50eZx/zJwtBq65nms3N9VBYu5LTjJ883oBFkTyXRlCB/ZGGwqYpJJHA5zW2Ibhl5ngITfow==" }, "@sinonjs/commons": { "version": "1.8.3", @@ -23885,24 +23938,24 @@ } }, "@tanstack/query-core": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.0.10.tgz", - "integrity": "sha512-9LsABpZXkWZHi4P1ozRETEDXQocLAxVzQaIhganxbNuz/uA3PsCAJxJTiQrknG5htLMzOF5MqM9G10e6DCxV1A==" + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", + "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==" }, "@tanstack/react-query": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.0.10.tgz", - "integrity": "sha512-Wn5QhZUE5wvr6rGClV7KeQIUsdTmYR9mgmMZen7DSRWauHW2UTynFg3Kkf6pw+XlxxOLsyLWwz/Q6q1lSpM3TQ==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.2.3.tgz", + "integrity": "sha512-JLaMOxoJTkiAu7QpevRCt2uI/0vd3E8K/rSlCuRgWlcW5DeJDFpDS5kfzmLO5MOcD97fgsJRrDbxDORxR1FdJA==", "requires": { - "@tanstack/query-core": "^4.0.0-beta.1", + "@tanstack/query-core": "4.2.3", "@types/use-sync-external-store": "^0.0.3", "use-sync-external-store": "^1.2.0" } }, "@tanstack/react-query-devtools": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-4.0.10.tgz", - "integrity": "sha512-3J7LLYQjfjTI0DbPo0bA+M3l4kdvYSWAqihpeG1u93WVyZj0OEFviUv+4cK7+k2AVgQJAPMZ5xvtewKxOOFVrw==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-4.2.3.tgz", + "integrity": "sha512-0PH8n824BnFyMrtv7q5uLS0b7jYg2tDH8vU4etkSYzV1uL4RJjiqMh7Gyi8qhYCwM+khlrkRYlNZvE0cxlp3SQ==", "requires": { "@tanstack/match-sorter-utils": "^8.0.0-alpha.82", "@types/use-sync-external-store": "^0.0.3", @@ -23933,9 +23986,9 @@ } }, "aria-query": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.0.tgz", - "integrity": "sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==" + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.2.tgz", + "integrity": "sha512-eigU3vhqSO+Z8BKDnVLN/ompjhf3pYzecKXz8+whRy+9gZu8n1TCGfwzQUUPnqdHl9ax1Hr9031orZ+UOEYr7Q==" }, "chalk": { "version": "4.1.2", @@ -23999,9 +24052,9 @@ } }, "aria-query": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.0.tgz", - "integrity": "sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==" + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.2.tgz", + "integrity": "sha512-eigU3vhqSO+Z8BKDnVLN/ompjhf3pYzecKXz8+whRy+9gZu8n1TCGfwzQUUPnqdHl9ax1Hr9031orZ+UOEYr7Q==" }, "chalk": { "version": "3.0.0", @@ -24145,9 +24198,9 @@ } }, "@types/eslint": { - "version": "8.4.5", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.5.tgz", - "integrity": "sha512-dhsC09y1gpJWnK+Ff4SGvCuSnk9DaU0BJZSzOwa6GVSg65XtTugLBITDAAzRU5duGBoXBHpdR/9jHGxJjNflJQ==", + "version": "8.4.6", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.6.tgz", + "integrity": "sha512-/fqTbjxyFUaYNO7VcW5g+4npmqVACz1bB7RTHYuLj+PRjw9hrCwrUXVQFpChUS0JsyEFvMZ7U/PfmvWgxJhI9g==", "requires": { "@types/estree": "*", "@types/json-schema": "*" @@ -24255,9 +24308,9 @@ "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" }, "@types/node": { - "version": "16.11.47", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.47.tgz", - "integrity": "sha512-fpP+jk2zJ4VW66+wAMFoBJlx1bxmBKx4DUFf68UHgdGCOuyUTDlLWqsaNPJh7xhNDykyJ9eIzAygilP/4WoN8g==" + "version": "16.11.56", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.56.tgz", + "integrity": "sha512-aFcUkv7EddxxOa/9f74DINReQ/celqH8DiB3fRYgVDM2Xm5QJL8sl80QKuAnGvwAsMn+H3IFA6WCrQh1CY7m1A==" }, "@types/parse-json": { "version": "4.0.0", @@ -24450,13 +24503,13 @@ "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" }, "@typescript-eslint/eslint-plugin": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.33.0.tgz", - "integrity": "sha512-jHvZNSW2WZ31OPJ3enhLrEKvAZNyAFWZ6rx9tUwaessTc4sx9KmgMNhVcqVAl1ETnT5rU5fpXTLmY9YvC1DCNg==", + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.35.1.tgz", + "integrity": "sha512-RBZZXZlI4XCY4Wzgy64vB+0slT9+yAPQRjj/HSaRwUot33xbDjF1oN9BLwOLTewoOI0jothIltZRe9uJCHf8gg==", "requires": { - "@typescript-eslint/scope-manager": "5.33.0", - "@typescript-eslint/type-utils": "5.33.0", - "@typescript-eslint/utils": "5.33.0", + "@typescript-eslint/scope-manager": "5.35.1", + "@typescript-eslint/type-utils": "5.35.1", + "@typescript-eslint/utils": "5.35.1", "debug": "^4.3.4", "functional-red-black-tree": "^1.0.1", "ignore": "^5.2.0", @@ -24466,55 +24519,55 @@ } }, "@typescript-eslint/experimental-utils": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.33.0.tgz", - "integrity": "sha512-NvRsNe+T90QrSVlgdV9/U8/chfqGmShvKUE7hWZTAUUCF6hZty/R+eMPVGldKcUDq7uRQaK6+V8gv5OwVDqC+g==", + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.35.1.tgz", + "integrity": "sha512-nF7JD9alMkhEx50QYDUdP8koeHtldnm7EfZkr68ikkc87ffFBIPkH3dqoWyOeQeIiJicB0uHzpMXKR6PP+1Jbg==", "requires": { - "@typescript-eslint/utils": "5.33.0" + "@typescript-eslint/utils": "5.35.1" } }, "@typescript-eslint/parser": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.33.0.tgz", - "integrity": "sha512-cgM5cJrWmrDV2KpvlcSkelTBASAs1mgqq+IUGKJvFxWrapHpaRy5EXPQz9YaKF3nZ8KY18ILTiVpUtbIac86/w==", + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.35.1.tgz", + "integrity": "sha512-XL2TBTSrh3yWAsMYpKseBYTVpvudNf69rPOWXWVBI08My2JVT5jR66eTt4IgQFHA/giiKJW5dUD4x/ZviCKyGg==", "requires": { - "@typescript-eslint/scope-manager": "5.33.0", - "@typescript-eslint/types": "5.33.0", - "@typescript-eslint/typescript-estree": "5.33.0", + "@typescript-eslint/scope-manager": "5.35.1", + "@typescript-eslint/types": "5.35.1", + "@typescript-eslint/typescript-estree": "5.35.1", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.33.0.tgz", - "integrity": "sha512-/Jta8yMNpXYpRDl8EwF/M8It2A9sFJTubDo0ATZefGXmOqlaBffEw0ZbkbQ7TNDK6q55NPHFshGBPAZvZkE8Pw==", + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.35.1.tgz", + "integrity": "sha512-kCYRSAzIW9ByEIzmzGHE50NGAvAP3wFTaZevgWva7GpquDyFPFcmvVkFJGWJJktg/hLwmys/FZwqM9EKr2u24Q==", "requires": { - "@typescript-eslint/types": "5.33.0", - "@typescript-eslint/visitor-keys": "5.33.0" + "@typescript-eslint/types": "5.35.1", + "@typescript-eslint/visitor-keys": "5.35.1" } }, "@typescript-eslint/type-utils": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.33.0.tgz", - "integrity": "sha512-2zB8uEn7hEH2pBeyk3NpzX1p3lF9dKrEbnXq1F7YkpZ6hlyqb2yZujqgRGqXgRBTHWIUG3NGx/WeZk224UKlIA==", + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.35.1.tgz", + "integrity": "sha512-8xT8ljvo43Mp7BiTn1vxLXkjpw8wS4oAc00hMSB4L1/jIiYbjjnc3Qp2GAUOG/v8zsNCd1qwcqfCQ0BuishHkw==", "requires": { - "@typescript-eslint/utils": "5.33.0", + "@typescript-eslint/utils": "5.35.1", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.33.0.tgz", - "integrity": "sha512-nIMt96JngB4MYFYXpZ/3ZNU4GWPNdBbcB5w2rDOCpXOVUkhtNlG2mmm8uXhubhidRZdwMaMBap7Uk8SZMU/ppw==" + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.35.1.tgz", + "integrity": "sha512-FDaujtsH07VHzG0gQ6NDkVVhi1+rhq0qEvzHdJAQjysN+LHDCKDKCBRlZFFE0ec0jKxiv0hN63SNfExy0KrbQQ==" }, "@typescript-eslint/typescript-estree": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.33.0.tgz", - "integrity": "sha512-tqq3MRLlggkJKJUrzM6wltk8NckKyyorCSGMq4eVkyL5sDYzJJcMgZATqmF8fLdsWrW7OjjIZ1m9v81vKcaqwQ==", + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.35.1.tgz", + "integrity": "sha512-JUqE1+VRTGyoXlDWWjm6MdfpBYVq+hixytrv1oyjYIBEOZhBCwtpp5ZSvBt4wIA1MKWlnaC2UXl2XmYGC3BoQA==", "requires": { - "@typescript-eslint/types": "5.33.0", - "@typescript-eslint/visitor-keys": "5.33.0", + "@typescript-eslint/types": "5.35.1", + "@typescript-eslint/visitor-keys": "5.35.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -24523,14 +24576,14 @@ } }, "@typescript-eslint/utils": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.33.0.tgz", - "integrity": "sha512-JxOAnXt9oZjXLIiXb5ZIcZXiwVHCkqZgof0O8KPgz7C7y0HS42gi75PdPlqh1Tf109M0fyUw45Ao6JLo7S5AHw==", + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.35.1.tgz", + "integrity": "sha512-v6F8JNXgeBWI4pzZn36hT2HXXzoBBBJuOYvoQiaQaEEjdi5STzux3Yj8v7ODIpx36i/5s8TdzuQ54TPc5AITQQ==", "requires": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.33.0", - "@typescript-eslint/types": "5.33.0", - "@typescript-eslint/typescript-estree": "5.33.0", + "@typescript-eslint/scope-manager": "5.35.1", + "@typescript-eslint/types": "5.35.1", + "@typescript-eslint/typescript-estree": "5.35.1", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" }, @@ -24552,11 +24605,11 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.33.0.tgz", - "integrity": "sha512-/XsqCzD4t+Y9p5wd9HZiptuGKBlaZO5showwqODii5C0nZawxWLF+Q6k5wYHBrQv96h6GYKyqqMHCSTqta8Kiw==", + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.35.1.tgz", + "integrity": "sha512-cEB1DvBVo1bxbW/S5axbGPE6b7FIMAbo3w+AGq6zNDA7+NYJOIkKj/sInfTv4edxd4PxJSgdN4t6/pbvgA+n5g==", "requires": { - "@typescript-eslint/types": "5.33.0", + "@typescript-eslint/types": "5.35.1", "eslint-visitor-keys": "^3.3.0" } }, @@ -24838,11 +24891,6 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" - }, - "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==" } } }, @@ -24872,14 +24920,14 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" - }, - "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==" } } }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==" + }, "address": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/address/-/address-1.2.0.tgz", @@ -24978,9 +25026,9 @@ } }, "antd": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/antd/-/antd-4.22.4.tgz", - "integrity": "sha512-u7l68PhSJMxyZmCNw+jwaeurSAaE+bU+lB0SPRHLfOFJR6xRudntvRoQdiEFOD5FZ3eeqz4lYQ3RZZRIarmceg==", + "version": "4.22.8", + "resolved": "https://registry.npmjs.org/antd/-/antd-4.22.8.tgz", + "integrity": "sha512-mqHuCg9itZX+z6wk+mvRBcfz/U9iiIXS4LoNkyo8X/UBgdN8CoetFmrdvA1UQy1BuWa0/n62LiS1LatdvoTuHw==", "requires": { "@ant-design/colors": "^6.0.0", "@ant-design/icons": "^4.7.0", @@ -24996,14 +25044,14 @@ "rc-checkbox": "~2.3.0", "rc-collapse": "~3.3.0", "rc-dialog": "~8.9.0", - "rc-drawer": "~5.1.0-alpha.1", + "rc-drawer": "~5.1.0", "rc-dropdown": "~4.0.0", "rc-field-form": "~1.27.0", "rc-image": "~5.7.0", "rc-input": "~0.0.1-alpha.5", "rc-input-number": "~7.3.5", "rc-mentions": "~1.9.1", - "rc-menu": "~9.6.0", + "rc-menu": "~9.6.3", "rc-motion": "^2.6.1", "rc-notification": "~4.6.0", "rc-pagination": "~3.1.17", @@ -25042,6 +25090,11 @@ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" }, + "arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -25909,9 +25962,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001375", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001375.tgz", - "integrity": "sha512-kWIMkNzLYxSvnjy0hL8w1NOaWNr2rn39RTAVyIwcw8juu60bZDWiF1/loOYANzjtJmy6qPgNmn38ro5Pygagdw==" + "version": "1.0.30001383", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001383.tgz", + "integrity": "sha512-swMpEoTp5vDoGBZsYZX7L7nXHe6dsHxi9o6/LKf/f0LukVtnrxly5GVb/fWdCDTqi/yw6Km6tiJ0pmBacm0gbg==" }, "case-sensitive-paths-webpack-plugin": { "version": "2.4.0", @@ -26356,14 +26409,14 @@ } }, "core-js": { - "version": "3.24.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.24.1.tgz", - "integrity": "sha512-0QTBSYSUZ6Gq21utGzkfITDylE8jWC9Ne1D2MrhvlsZBI1x39OdDIVbzSqtgMndIy6BlHxBXpMGqzZmnztg2rg==" + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==" }, "core-js-compat": { - "version": "3.24.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.24.1.tgz", - "integrity": "sha512-XhdNAGeRnTpp8xbD+sR/HFDK9CbeeeqXT6TuofXh3urqEevzkWmLRgrVoykodsw8okqo2pu1BOmuCKrHx63zdw==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.25.0.tgz", + "integrity": "sha512-extKQM0g8/3GjFx9US12FAgx8KJawB7RCQ5y8ipYLbmfzEzmFRWdDjIlxDx82g7ygcNG85qMVUSRyABouELdow==", "requires": { "browserslist": "^4.21.3", "semver": "7.0.0" @@ -26377,9 +26430,9 @@ } }, "core-js-pure": { - "version": "3.24.1", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.24.1.tgz", - "integrity": "sha512-r1nJk41QLLPyozHUUPmILCEMtMw24NG4oWK6RbsDdjzQgg9ZvrUsPBj1MnG0wXXp1DCDU6j+wUvEmBSrtRbLXg==" + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.25.0.tgz", + "integrity": "sha512-IeHpLwk3uoci37yoI2Laty59+YqH9x5uR65/yiA0ARAJrTrN4YU0rmauLWfvqOuk77SlNJXj2rM6oT/dBD87+A==" }, "core-util-is": { "version": "1.0.3", @@ -27120,9 +27173,9 @@ "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==" }, "cssdb": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-6.6.3.tgz", - "integrity": "sha512-7GDvDSmE+20+WcSMhP17Q1EVWUrLlbxxpMDqG731n8P99JhnQZHR9YvtjPvEHfjFUjvQJvdpKCjlKOX+xe4UVA==" + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.0.1.tgz", + "integrity": "sha512-pT3nzyGM78poCKLAEy2zWIVX2hikq6dIrjuZzLV98MumBg+xMTNYfHx7paUlfiRTgg91O/vR889CIf+qiv79Rw==" }, "cssesc": { "version": "3.0.0", @@ -27130,9 +27183,9 @@ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" }, "cssnano": { - "version": "5.1.12", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.12.tgz", - "integrity": "sha512-TgvArbEZu0lk/dvg2ja+B7kYoD7BBCmn3+k58xD0qjrGHsFzXY/wKTo9M5egcUCabPol05e/PVoIu79s2JN4WQ==", + "version": "5.1.13", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.13.tgz", + "integrity": "sha512-S2SL2ekdEz6w6a2epXn4CmMKU4K3KpcyXLKfAYc9UQQqJRkD/2eLUG0vJ3Db/9OvO5GuAdgXw3pFbR6abqghDQ==", "requires": { "cssnano-preset-default": "^5.2.12", "lilconfig": "^2.0.3", @@ -27256,14 +27309,14 @@ } }, "date-fns": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.1.tgz", - "integrity": "sha512-dlLD5rKaKxpFdnjrs+5azHDFOPEu4ANy/LTh04A1DTzMM7qoajmKCBc8pkKRFT41CNzw+4gQh79X5C+Jq27HAw==" + "version": "2.29.2", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.2.tgz", + "integrity": "sha512-0VNbwmWJDS/G3ySwFSJA3ayhbURMTJLtwM2DTxf9CWondCnh6DTNlO9JgRSq6ibf4eD0lfMJNBxUdEAHHix+bA==" }, "dayjs": { - "version": "1.11.4", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.4.tgz", - "integrity": "sha512-Zj/lPM5hOvQ1Bf7uAvewDaUcsJoI6JmNqmHhHl3nyumwe0XHwt8sWdOVAPACJzCebL8gQCi+K49w7iKWnGwX9g==" + "version": "1.11.5", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.5.tgz", + "integrity": "sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA==" }, "debug": { "version": "4.3.4", @@ -27274,9 +27327,9 @@ } }, "decimal.js": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", - "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==" + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.0.tgz", + "integrity": "sha512-Nv6ENEzyPQ6AItkGwLE2PGKinZZ9g59vSh2BeH6NqPu0OTKZ5ruJsVqh/orbAnqXc9pBbgXAIrc2EyaCj8NpGg==" }, "decode-uri-component": { "version": "0.2.0", @@ -27607,9 +27660,9 @@ } }, "electron-to-chromium": { - "version": "1.4.213", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.213.tgz", - "integrity": "sha512-+3DbGHGOCHTVB/Ms63bGqbyC1b8y7Fk86+7ltssB8NQrZtSCvZG6eooSl9U2Q0yw++fL2DpHKOdTU0NVEkFObg==" + "version": "1.4.233", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.233.tgz", + "integrity": "sha512-ejwIKXTg1wqbmkcRJh9Ur3hFGHFDZDw1POzdsVrB2WZjgRuRMHIQQKNpe64N/qh3ZtH2otEoRoS+s6arAAuAAw==" }, "elliptic": { "version": "6.5.4", @@ -27827,13 +27880,14 @@ } }, "eslint": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.21.0.tgz", - "integrity": "sha512-/XJ1+Qurf1T9G2M5IHrsjp+xrGT73RZf23xA1z5wB1ZzzEAWSZKvRwhWxTFp1rvkvCfwcvAUNAP31bhKTTGfDA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.23.0.tgz", + "integrity": "sha512-pBG/XOn0MsJcKcTRLr27S5HpzQo4kLr+HjLQIyK4EiCsijDl/TB+h5uEuJU6bQ8Edvwz1XWOjpaP2qgnXGpTcA==", "requires": { - "@eslint/eslintrc": "^1.3.0", + "@eslint/eslintrc": "^1.3.1", "@humanwhocodes/config-array": "^0.10.4", "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", + "@humanwhocodes/module-importer": "^1.0.1", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -27843,7 +27897,7 @@ "eslint-scope": "^7.1.1", "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.3", + "espree": "^9.4.0", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -27868,8 +27922,7 @@ "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "text-table": "^0.2.0" }, "dependencies": { "ansi-styles": { @@ -27989,12 +28042,11 @@ } }, "eslint-module-utils": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz", - "integrity": "sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==", + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", + "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", "requires": { - "debug": "^3.2.7", - "find-up": "^2.1.0" + "debug": "^3.2.7" }, "dependencies": { "debug": { @@ -28004,49 +28056,6 @@ "requires": { "ms": "^2.1.1" } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==" - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" } } }, @@ -28138,9 +28147,9 @@ } }, "eslint-plugin-react": { - "version": "7.30.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.30.1.tgz", - "integrity": "sha512-NbEvI9jtqO46yJA3wcRF9Mo0lF9T/jhdHqhCHXiXtD+Zcb98812wvokjWpU7Q4QH5edo6dmqrukxVvWWXHlsUg==", + "version": "7.31.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.1.tgz", + "integrity": "sha512-j4/2xWqt/R7AZzG8CakGHA6Xa/u7iR8Q3xCxY+AUghdT92bnIDOBEefV456OeH0QvBcroVc0eyvrrLSyQGYIfg==", "requires": { "array-includes": "^3.1.5", "array.prototype.flatmap": "^1.3.0", @@ -28299,9 +28308,9 @@ } }, "espree": { - "version": "9.3.3", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.3.tgz", - "integrity": "sha512-ORs1Rt/uQTqUKjDdGCyrtYxbazf5umATSf/K4qxjmZHORR6HJk+2s/2Pqe+Kk49HHINC/xNIrGfgh8sZcll0ng==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", + "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", "requires": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", @@ -28797,9 +28806,9 @@ } }, "flatted": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz", - "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==" + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" }, "flush-write-stream": { "version": "1.1.1", @@ -30221,37 +30230,82 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, - "jest-config": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", - "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "requires": { - "@babel/core": "^7.8.0", - "@jest/test-sequencer": "^27.5.1", - "@jest/types": "^27.5.1", - "babel-jest": "^27.5.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.1", - "graceful-fs": "^4.2.9", - "jest-circus": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-jasmine2": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" + "has-flag": "^4.0.0" + } + } + } + }, + "jest-config": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", + "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", + "requires": { + "@babel/core": "^7.8.0", + "@jest/test-sequencer": "^27.5.1", + "@jest/types": "^27.5.1", + "babel-jest": "^27.5.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.9", + "jest-circus": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-jasmine2": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" } }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -32366,9 +32420,9 @@ } }, "object.assign": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.3.tgz", - "integrity": "sha512-ZFJnX3zltyjcYJL0RoCJuzb+11zWGyaDbjgxZbdV7rFEcHQuYxrZqhow67aA7xpes6LhojyFDaBKAFfogQrikA==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", "requires": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -33041,6 +33095,15 @@ "postcss-value-parser": "^4.2.0" } }, + "postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "requires": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + } + }, "postcss-loader": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", @@ -33287,56 +33350,58 @@ } }, "postcss-preset-env": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.7.2.tgz", - "integrity": "sha512-1q0ih7EDsZmCb/FMDRvosna7Gsbdx8CvYO5hYT120hcp2ZAuOHpSzibujZ4JpIUcAC02PG6b+eftxqjTFh5BNA==", - "requires": { - "@csstools/postcss-cascade-layers": "^1.0.4", - "@csstools/postcss-color-function": "^1.1.0", - "@csstools/postcss-font-format-keywords": "^1.0.0", - "@csstools/postcss-hwb-function": "^1.0.1", - "@csstools/postcss-ic-unit": "^1.0.0", - "@csstools/postcss-is-pseudo-class": "^2.0.6", - "@csstools/postcss-normalize-display-values": "^1.0.0", - "@csstools/postcss-oklab-function": "^1.1.0", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.8.0.tgz", + "integrity": "sha512-leqiqLOellpLKfbHkD06E04P6d9ZQ24mat6hu4NSqun7WG0UhspHR5Myiv/510qouCjoo4+YJtNOqg5xHaFnCA==", + "requires": { + "@csstools/postcss-cascade-layers": "^1.0.5", + "@csstools/postcss-color-function": "^1.1.1", + "@csstools/postcss-font-format-keywords": "^1.0.1", + "@csstools/postcss-hwb-function": "^1.0.2", + "@csstools/postcss-ic-unit": "^1.0.1", + "@csstools/postcss-is-pseudo-class": "^2.0.7", + "@csstools/postcss-nested-calc": "^1.0.0", + "@csstools/postcss-normalize-display-values": "^1.0.1", + "@csstools/postcss-oklab-function": "^1.1.1", "@csstools/postcss-progressive-custom-properties": "^1.3.0", - "@csstools/postcss-stepped-value-functions": "^1.0.0", - "@csstools/postcss-trigonometric-functions": "^1.0.1", - "@csstools/postcss-unset-value": "^1.0.1", - "autoprefixer": "^10.4.7", - "browserslist": "^4.21.0", + "@csstools/postcss-stepped-value-functions": "^1.0.1", + "@csstools/postcss-text-decoration-shorthand": "^1.0.0", + "@csstools/postcss-trigonometric-functions": "^1.0.2", + "@csstools/postcss-unset-value": "^1.0.2", + "autoprefixer": "^10.4.8", + "browserslist": "^4.21.3", "css-blank-pseudo": "^3.0.3", "css-has-pseudo": "^3.0.4", "css-prefers-color-scheme": "^6.0.3", - "cssdb": "^6.6.3", - "postcss-attribute-case-insensitive": "^5.0.1", + "cssdb": "^7.0.0", + "postcss-attribute-case-insensitive": "^5.0.2", "postcss-clamp": "^4.1.0", - "postcss-color-functional-notation": "^4.2.3", + "postcss-color-functional-notation": "^4.2.4", "postcss-color-hex-alpha": "^8.0.4", - "postcss-color-rebeccapurple": "^7.1.0", + "postcss-color-rebeccapurple": "^7.1.1", "postcss-custom-media": "^8.0.2", "postcss-custom-properties": "^12.1.8", "postcss-custom-selectors": "^6.0.3", - "postcss-dir-pseudo-class": "^6.0.4", - "postcss-double-position-gradients": "^3.1.1", + "postcss-dir-pseudo-class": "^6.0.5", + "postcss-double-position-gradients": "^3.1.2", "postcss-env-function": "^4.0.6", "postcss-focus-visible": "^6.0.4", "postcss-focus-within": "^5.0.4", "postcss-font-variant": "^5.0.0", - "postcss-gap-properties": "^3.0.3", - "postcss-image-set-function": "^4.0.6", + "postcss-gap-properties": "^3.0.5", + "postcss-image-set-function": "^4.0.7", "postcss-initial": "^4.0.1", - "postcss-lab-function": "^4.2.0", + "postcss-lab-function": "^4.2.1", "postcss-logical": "^5.0.4", "postcss-media-minmax": "^5.0.0", - "postcss-nesting": "^10.1.9", + "postcss-nesting": "^10.1.10", "postcss-opacity-percentage": "^1.1.2", - "postcss-overflow-shorthand": "^3.0.3", + "postcss-overflow-shorthand": "^3.0.4", "postcss-page-break": "^3.0.4", - "postcss-place": "^7.0.4", - "postcss-pseudo-class-any-link": "^7.1.5", + "postcss-place": "^7.0.5", + "postcss-pseudo-class-any-link": "^7.1.6", "postcss-replace-overflow-wrap": "^4.0.0", - "postcss-selector-not": "^6.0.0", + "postcss-selector-not": "^6.0.1", "postcss-value-parser": "^4.2.0" } }, @@ -33639,6 +33704,11 @@ "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==" }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -33719,9 +33789,9 @@ } }, "rc-cascader": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.6.1.tgz", - "integrity": "sha512-+GmN2Z0IybKT45t0Z94jkjmsOHGxAliobR2tzt05/Gw0AKBYLHX5bdvsVXR7abPnarYyYzZ/cWe8CoFgDjAFNw==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.6.2.tgz", + "integrity": "sha512-sf2otpazlROTzkD3nZVfIzXmfBLiEOBTXA5wxozGXBpS902McDpvF0bdcYBu5hN+rviEAm6Mh9cLXNQ1Ty8wKQ==", "requires": { "@babel/runtime": "^7.12.5", "array-tree-filter": "^2.1.0", @@ -33827,9 +33897,9 @@ } }, "rc-mentions": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-1.9.1.tgz", - "integrity": "sha512-6VBaEkJjYdGGxAygQvE2NaIegAzLJSDodgzpoV+vonUUCZ4A/d8izVlc2JqCYa0Yi15HiDcWyfRgJYI7OKTILg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-1.9.2.tgz", + "integrity": "sha512-uxb/lzNnEGmvraKWNGE6KXMVXvt8RQv9XW8R0Dqi3hYsyPiAZeHRCHQKdLARuk5YBhFhZ6ga55D/8XuY367g3g==", "requires": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.6", @@ -33840,9 +33910,9 @@ } }, "rc-menu": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.6.2.tgz", - "integrity": "sha512-sSobfm30OAw6XfVaj+rEkBfalLxbZ3uOsB876MCG6NmwXQGSKRv+arTBnJnJqAmCGh2dMyb/Jf9kTCMpII6RTg==", + "version": "9.6.3", + "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.6.3.tgz", + "integrity": "sha512-KY9QilKWgkJZ0JSpOBgIpQF2wMRRodRxpIMYyIJ3Nd5N6xfVLOxXCxevHcBplt+Ez7MhUF+I03MuAKqWQJLZgw==", "requires": { "@babel/runtime": "^7.10.1", "classnames": "2.x", @@ -34056,9 +34126,9 @@ } }, "rc-tree-select": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.4.0.tgz", - "integrity": "sha512-reRbOqC7Ic/nQocJAJeCl4n6nJUY3NoqiwRXKvhjgZJU7NGr9vIccXEsY+Lghkw5UMpPoxGsIJB0jiAvM18XYA==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.4.1.tgz", + "integrity": "sha512-xhXnKP8Stu2Q7wTcjJaSzSOLd4wmFtUZOwmy1cioaWyPbpiKlYdnALXA/9U49HOaV3KFXdRHE9Yi0KYED7yOAQ==", "requires": { "@babel/runtime": "^7.10.1", "classnames": "2.x", @@ -34137,6 +34207,32 @@ "whatwg-fetch": "^3.6.2" } }, + "react-app-rewire-alias": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/react-app-rewire-alias/-/react-app-rewire-alias-1.1.7.tgz", + "integrity": "sha512-vn4xU3E/wzh2/fGxda9ZQ6CtW2XdZB/WxAgNOdNPyUcX3hA3mh+kCRGwo19gSjzeTPpoZQwZRblHabLr6mwOTw==", + "dev": true, + "requires": {} + }, + "react-app-rewired": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-app-rewired/-/react-app-rewired-2.2.1.tgz", + "integrity": "sha512-uFQWTErXeLDrMzOJHKp0h8P1z0LV9HzPGsJ6adOtGlA/B9WfT6Shh4j2tLTTGlXOfiVx6w6iWpp7SOC5pvk+gA==", + "dev": true, + "peer": true, + "requires": { + "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "peer": true + } + } + }, "react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -34371,9 +34467,9 @@ } }, "recoil": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/recoil/-/recoil-0.7.4.tgz", - "integrity": "sha512-sCXvQGMfSprkNU4ZRkJV4B0qFQSURJMgsICqY1952WRlg66NMwYqi6n67vhnhn0qw4zHU1gHXJuMvRDaiRNFZw==", + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/recoil/-/recoil-0.7.5.tgz", + "integrity": "sha512-GVShsj5+M/2GULWBs5WBJGcsNis/d3YvDiaKjYh3mLKXftjtmk9kfaQ8jwjoIXySCwn8/RhgJ4Sshwgzj2UpFA==", "requires": { "hamt_plus": "1.0.2" } @@ -34660,9 +34756,9 @@ } }, "rollup": { - "version": "2.77.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.77.2.tgz", - "integrity": "sha512-m/4YzYgLcpMQbxX3NmAqDvwLATZzxt8bIegO78FZLl+lAgKJBd1DRAOeEiZcKOIOPjxE6ewHWHNgGEalFXuz1g==", + "version": "2.78.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", + "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", "requires": { "fsevents": "~2.3.2" } @@ -35284,9 +35380,9 @@ } }, "spdx-license-ids": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", - "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==" + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", + "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==" }, "spdy": { "version": "4.0.2", @@ -35821,24 +35917,10 @@ "resolve": "^1.22.1" }, "dependencies": { - "arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" - }, "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "postcss-load-config": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", - "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", - "requires": { - "lilconfig": "^2.0.5", - "yaml": "^1.10.2" - } } } }, @@ -35880,9 +35962,9 @@ } }, "terser": { - "version": "5.14.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz", - "integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", + "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", "requires": { "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", @@ -35898,15 +35980,15 @@ } }, "terser-webpack-plugin": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.3.tgz", - "integrity": "sha512-Fx60G5HNYknNTNQnzQ1VePRuu89ZVYWfjRAeT5rITuCY/1b08s49e5kSQwHDirKZWuoKOBRFS98EUUoZ9kLEwQ==", + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.5.tgz", + "integrity": "sha512-AOEDLDxD2zylUGf/wxHxklEkOe2/r+seuyOWujejFrIxHf11brA1/dWQNIgXa1c6/Wkxgu7zvv0JhOWfc2ELEA==", "requires": { - "@jridgewell/trace-mapping": "^0.3.7", + "@jridgewell/trace-mapping": "^0.3.14", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.0", - "terser": "^5.7.2" + "terser": "^5.14.1" } }, "test-exclude": { @@ -36038,19 +36120,20 @@ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" }, "tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz", + "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==", "requires": { "psl": "^1.1.33", "punycode": "^2.1.1", - "universalify": "^0.1.2" + "universalify": "^0.2.0", + "url-parse": "^1.5.3" }, "dependencies": { "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==" } } }, @@ -36159,9 +36242,9 @@ } }, "typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==" + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz", + "integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==" }, "unbox-primitive": { "version": "1.0.2", @@ -36334,6 +36417,15 @@ } } }, + "url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", @@ -36391,11 +36483,6 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==" - }, "v8-to-istanbul": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", diff --git a/package.json b/package.json index 14a192a..41fba05 100644 --- a/package.json +++ b/package.json @@ -50,5 +50,8 @@ "last 1 firefox version", "last 1 safari version" ] + }, + "devDependencies": { + "react-app-rewire-alias": "^1.1.7" } } diff --git a/src/App.css b/src/App.css index 88606d8..74b5e05 100644 --- a/src/App.css +++ b/src/App.css @@ -1,12 +1,38 @@ -@import '~antd/dist/antd.css'; - -#components-layout-demo-fixed .logo { - float: left; - width: 120px; - height: 31px; - margin: 16px 24px 16px 0; - background: rgba(255, 255, 255, 0.2); -} -.site-layout .site-layout-background { - background: #fff; -} \ No newline at end of file +.App { + text-align: center; +} + +.App-logo { + height: 40vmin; + pointer-events: none; +} + +@media (prefers-reduced-motion: no-preference) { + .App-logo { + animation: App-logo-spin infinite 20s linear; + } +} + +.App-header { + background-color: #282c34; + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: calc(10px + 2vmin); + color: white; +} + +.App-link { + color: #61dafb; +} + +@keyframes App-logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} diff --git a/src/App.test.tsx b/src/App.test.tsx index 47abaa1..d1af01f 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -1,14 +1,32 @@ import React from 'react'; +import { + BrowserRouter, +} from "react-router-dom"; import { render, screen } from '@testing-library/react'; -import { BrowserRouter } from "react-router-dom"; +import '@app/index.css'; import App from './App'; +import { QueryClientProvider } from '@tanstack/react-query'; +import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; +import queryClient from '@plugins/QueryClient'; +import { + RecoilRoot, +} from 'recoil'; test('renders learn react link', () => { render( - - - + + + + + + + + + + ); - const linkElement = screen.getByText(/Test App/i); + + const linkElement = screen.getByText(/Redeemer Pace/i); + expect(linkElement).toBeInTheDocument(); }); diff --git a/src/api/endpoints/profile.ts b/src/api/endpoints/profile.ts index 8eecb8e..8bd8960 100644 --- a/src/api/endpoints/profile.ts +++ b/src/api/endpoints/profile.ts @@ -7,7 +7,7 @@ export type BaseDetail = { readonly homeworld: string readonly films: string[] readonly species: string[] - readonly vechiles: string[] + readonly vehicles: string[] readonly starships: string[] readonly url: string readonly created: Date @@ -74,9 +74,16 @@ export type GetProfileParams = { ids: number[] } - -export const getProfile = async ({ category, ids }: GetProfileParams) => { - if (!ids.length) { +/** + * Get the profiles according + * @param {Object} profile - The profiles to be requested + * @param {number[]} profile.ids - The list of ids to be requested by + * @param {string} profile.category - The category involved to call current specific profile. + * @example await getProfiles({ category: 'person', ids: [1,5,6] }); + * @returns {Promise>} + */ +export const getProfiles = async ({ category, ids }: GetProfileParams) => { + if (!ids || !ids.length) { return Promise.reject({ message: 'IDs is required', }) diff --git a/src/api/endpoints/search.ts b/src/api/endpoints/search.ts index 0c336c1..63a44a3 100644 --- a/src/api/endpoints/search.ts +++ b/src/api/endpoints/search.ts @@ -23,6 +23,17 @@ export type GetSearchParams = { searchValue: string } +/** + * Get the profiles according + * @param {Object} search - The profiles to be requested + * @param {string} search.searchValue - The value to search with + * @param {string=} search.category - The category to search from + * @example // All profiles to be searched + * await getSearch({ searchValue: 'luke' }); + * @example // Person profiles to be searched + * await getSearch({ category: SearchCategory.PERSON, searchValue: 'luke' }); + * @returns {Promise>} + */ export const getSearch = async ({ category = SearchCategory.ALL, searchValue }: GetSearchParams) => { if (!searchValue) { return Promise.reject({ diff --git a/src/components/profile/RelatedProfileList.tsx b/src/components/profile/RelatedProfileList.tsx index 7e04ccd..eb09b9a 100644 --- a/src/components/profile/RelatedProfileList.tsx +++ b/src/components/profile/RelatedProfileList.tsx @@ -15,7 +15,7 @@ interface RelatedProfileListStruct { endpointsRelated: string[] } -function RelatedProfileList({ categories = [], profileId, endpointsRelated = [] }: RelatedProfileListStruct) { +const RelatedProfileList = ({ categories = [], profileId, endpointsRelated = [] }: RelatedProfileListStruct) => { const category = useGetProfileCategories(endpointsRelated); const ids = useGetProfileIds(endpointsRelated); diff --git a/src/components/profile/RelatedProfileTabs.tsx b/src/components/profile/RelatedProfileTabs.tsx index eb7f2c5..04befae 100644 --- a/src/components/profile/RelatedProfileTabs.tsx +++ b/src/components/profile/RelatedProfileTabs.tsx @@ -14,7 +14,7 @@ interface RelatedProfileTabsStruct { } } -function RelatedProfileTabs({ currentCategory, profileId, categories, profiles }: RelatedProfileTabsStruct) { +const RelatedProfileTabs = ({ currentCategory, profileId, categories, profiles }: RelatedProfileTabsStruct) => { return ( { diff --git a/src/components/search/SearchList.tsx b/src/components/search/SearchList.tsx index 09c6b00..1c12af6 100644 --- a/src/components/search/SearchList.tsx +++ b/src/components/search/SearchList.tsx @@ -1,4 +1,4 @@ -import React, { memo, useCallback, useEffect } from 'react'; +import { memo, useCallback, useEffect } from 'react'; import { useNavigate } from "react-router-dom"; import { List } from 'antd'; import { useSearch } from '@hooks/search/useSearch' @@ -10,7 +10,7 @@ import useSearchCanRefetch from '@hooks/search/atoms/useSearchCanRefetch'; import GeneralError from '@pages/errors/general'; import SearchListItem from '@components/search/SearchListItem'; -function SearchList() { +const SearchList = () => { const { searchCategory } = useSearchCategory(); const { searchValue } = useSearchValue(); const { searchCanRefetch, setSearchCanRefetch } = useSearchCanRefetch(); diff --git a/src/components/search/SearchListItem.tsx b/src/components/search/SearchListItem.tsx index 7c66a40..5a51014 100644 --- a/src/components/search/SearchListItem.tsx +++ b/src/components/search/SearchListItem.tsx @@ -2,7 +2,7 @@ import React, { memo } from 'react'; import { Link } from "react-router-dom"; import { Skeleton, List } from 'antd'; import { MultiCategoryDetails } from '@api/endpoints/profile'; -import { useGetProfileEpisodesIds } from '@hooks/profile/useGetProfileEpisodeIds'; +import { useGetProfileEpisodesIds } from '@hooks/profile/useGetProfileEpisodesIds'; interface SearchListItemStruct { isLoading?: boolean | undefined, @@ -10,7 +10,7 @@ interface SearchListItemStruct { item: MultiCategoryDetails; } -function SearchListItem({ isLoading, index, item }: SearchListItemStruct) { +const SearchListItem = ({ isLoading, index, item }: SearchListItemStruct) => { const episodesIds = useGetProfileEpisodesIds(item.films); return ( diff --git a/src/hooks/profile/useDisplayableDetails.test.ts b/src/hooks/profile/useDisplayableDetails.test.ts new file mode 100644 index 0000000..ebbefc1 --- /dev/null +++ b/src/hooks/profile/useDisplayableDetails.test.ts @@ -0,0 +1,51 @@ +import { MultiCategoryDetails } from '@api/endpoints/profile'; +import { SearchCategory } from '@api/endpoints/search'; +import { useDisplayableDetails } from '@hooks/profile/useDisplayableDetails'; + +describe('[Hook] useDisplayableDetails', () => { + const excludedCategories = [SearchCategory.PEOPLE, SearchCategory.VEHICLES, SearchCategory.SPECIES, SearchCategory.PLANETS, SearchCategory.STARSHIPS]; + const currentProfile: MultiCategoryDetails = { + name: "Luke Skywalker", + height: 172, + mass: 77, + hair_color: "blond", + skin_color: "fair", + eye_color: "blue", + birth_year: "19BBY", + gender: "male", + homeworld: "https://swapi.dev/api/planets/1/", + films: [ + "https://swapi.dev/api/films/1/", + "https://swapi.dev/api/films/2/", + "https://swapi.dev/api/films/3/", + "https://swapi.dev/api/films/6/" + ], + species: [], + vehicles: [ + "https://swapi.dev/api/vehicles/14/", + "https://swapi.dev/api/vehicles/30/" + ], + starships: [ + "https://swapi.dev/api/starships/12/", + "https://swapi.dev/api/starships/22/" + ], + created: new Date("2014-12-09T13:50:51.644000Z"), + edited: new Date("2014-12-20T21:17:56.891000Z"), + url: "https://swapi.dev/api/people/1/" + } + + + it('Should return the result with specific fields only', () => { + const result = useDisplayableDetails(excludedCategories, currentProfile); + + const { name, url, homeworld, vehicles, species, starships, ...newProfile } = currentProfile; + + expect(JSON.stringify(result)).toBe(JSON.stringify(newProfile)); + }) + + it('Should not return the result with specific fields', () => { + const result = useDisplayableDetails(excludedCategories, currentProfile); + + expect(JSON.stringify(result)).not.toBe(JSON.stringify(currentProfile)); + }) +}) \ No newline at end of file diff --git a/src/hooks/profile/useDisplayableDetails.ts b/src/hooks/profile/useDisplayableDetails.ts index 8b9ae51..3406a51 100644 --- a/src/hooks/profile/useDisplayableDetails.ts +++ b/src/hooks/profile/useDisplayableDetails.ts @@ -4,10 +4,10 @@ type UseDisplayableDetailsStruct = (MultiCategoryDetails & { key: string }) -export const useDisplayableDetails = (viewableCategories: string[], currentProfile: MultiCategoryDetails): UseDisplayableDetailsStruct => { +export const useDisplayableDetails = (excludedCategories: string[], currentProfile: MultiCategoryDetails): UseDisplayableDetailsStruct => { return Object.keys(currentProfile) .filter((key: string) => ![ - ...viewableCategories, + ...excludedCategories, 'homeworld', 'url', 'characters', diff --git a/src/hooks/profile/useGetProfileCategories.test.ts b/src/hooks/profile/useGetProfileCategories.test.ts new file mode 100644 index 0000000..5eecd6b --- /dev/null +++ b/src/hooks/profile/useGetProfileCategories.test.ts @@ -0,0 +1,29 @@ +import { useGetProfileCategories } from '@hooks/profile/useGetProfileCategories'; + +describe('[Hook] useGetProfileCategories', () => { + const relatedEndpoints = [ + "https://swapi.dev/api/films/1/", + "https://swapi.dev/api/films/2/", + "https://swapi.dev/api/films/3/", + "https://swapi.dev/api/films/6/" + ] + + + it('Should return with the profile category', () => { + const result = useGetProfileCategories(relatedEndpoints); + + expect(result).toBe('films'); + }) + + it('Should not return the result different profile category', () => { + const result = useGetProfileCategories(relatedEndpoints); + + expect(result).not.toBe('vehicles'); + }) + + it('Should return empty undefined if nothing given', () => { + const result = useGetProfileCategories([]); + + expect(result).toBe(""); + }) +}) \ No newline at end of file diff --git a/src/hooks/profile/useGetProfileCategories.ts b/src/hooks/profile/useGetProfileCategories.ts index 1acc225..b563367 100644 --- a/src/hooks/profile/useGetProfileCategories.ts +++ b/src/hooks/profile/useGetProfileCategories.ts @@ -1,5 +1,9 @@ export const useGetProfileCategories = (endpointsRelated: string[]): string => { - const [first] = endpointsRelated; + const [first = ""] = endpointsRelated || []; + + if (!first) { + return ""; + } const [category] = first.replace('https://swapi.dev/api', '').split('/').filter((item) => item); diff --git a/src/hooks/profile/useGetProfileEpisodeIds.ts b/src/hooks/profile/useGetProfileEpisodeIds.ts deleted file mode 100644 index b5e761a..0000000 --- a/src/hooks/profile/useGetProfileEpisodeIds.ts +++ /dev/null @@ -1 +0,0 @@ -export const useGetProfileEpisodesIds = (films: string[] = []) => films.map((item) => item.match(/\d+/)) \ No newline at end of file diff --git a/src/hooks/profile/useGetProfileEpisodesIds.test.ts b/src/hooks/profile/useGetProfileEpisodesIds.test.ts new file mode 100644 index 0000000..2a609e0 --- /dev/null +++ b/src/hooks/profile/useGetProfileEpisodesIds.test.ts @@ -0,0 +1,33 @@ +import { useGetProfileEpisodesIds } from '@hooks/profile/useGetProfileEpisodesIds'; + +describe('[Hook] useGetProfileEpisodesIds', () => { + const relatedEndpoints = [ + "https://swapi.dev/api/films/1/", + "https://swapi.dev/api/films/2/", + "https://swapi.dev/api/films/3/", + "https://swapi.dev/api/films/6/" + ] + + + it('Should return with the profile category', () => { + const result = useGetProfileEpisodesIds(relatedEndpoints); + + expect(JSON.stringify(result)).toBe(JSON.stringify([ + 1,2,3,6 + ])); + }) + + it('Should not return the result different profile category', () => { + const result = useGetProfileEpisodesIds(relatedEndpoints); + + expect(JSON.stringify(result)).not.toBe(JSON.stringify([ + 1,2,3,5 + ])); + }) + + it('Should return empty array if nothing was given', () => { + const result = useGetProfileEpisodesIds([]); + + expect(JSON.stringify(result)).toBe(JSON.stringify([])); + }) +}) \ No newline at end of file diff --git a/src/hooks/profile/useGetProfileEpisodesIds.ts b/src/hooks/profile/useGetProfileEpisodesIds.ts new file mode 100644 index 0000000..1e54a76 --- /dev/null +++ b/src/hooks/profile/useGetProfileEpisodesIds.ts @@ -0,0 +1,5 @@ +export const useGetProfileEpisodesIds = (films: string[] = []) => films + .map((item) => item.match(/\d+/)) + .flat(2) + .filter((item) => item) + .map((num) => Number(num)) \ No newline at end of file diff --git a/src/hooks/profile/useGetProfileIds.test.ts b/src/hooks/profile/useGetProfileIds.test.ts new file mode 100644 index 0000000..2a609e0 --- /dev/null +++ b/src/hooks/profile/useGetProfileIds.test.ts @@ -0,0 +1,33 @@ +import { useGetProfileEpisodesIds } from '@hooks/profile/useGetProfileEpisodesIds'; + +describe('[Hook] useGetProfileEpisodesIds', () => { + const relatedEndpoints = [ + "https://swapi.dev/api/films/1/", + "https://swapi.dev/api/films/2/", + "https://swapi.dev/api/films/3/", + "https://swapi.dev/api/films/6/" + ] + + + it('Should return with the profile category', () => { + const result = useGetProfileEpisodesIds(relatedEndpoints); + + expect(JSON.stringify(result)).toBe(JSON.stringify([ + 1,2,3,6 + ])); + }) + + it('Should not return the result different profile category', () => { + const result = useGetProfileEpisodesIds(relatedEndpoints); + + expect(JSON.stringify(result)).not.toBe(JSON.stringify([ + 1,2,3,5 + ])); + }) + + it('Should return empty array if nothing was given', () => { + const result = useGetProfileEpisodesIds([]); + + expect(JSON.stringify(result)).toBe(JSON.stringify([])); + }) +}) \ No newline at end of file diff --git a/src/hooks/profile/useGetRelatedProfiles.test.ts b/src/hooks/profile/useGetRelatedProfiles.test.ts new file mode 100644 index 0000000..737c8fe --- /dev/null +++ b/src/hooks/profile/useGetRelatedProfiles.test.ts @@ -0,0 +1,75 @@ +import { MultiCategoryDetails } from '@api/endpoints/profile'; +import { SearchCategory } from '@api/endpoints/search'; +import { useGetRelatedProfiles } from '@hooks/profile/useGetRelatedProfiles'; + +describe('[Hook] useGetRelatedProfiles', () => { + const viewableCategories = [SearchCategory.PEOPLE, SearchCategory.VEHICLES, SearchCategory.SPECIES, SearchCategory.PLANETS, SearchCategory.STARSHIPS]; + const currentProfile: MultiCategoryDetails = { + name: "Luke Skywalker", + height: 172, + mass: 77, + hair_color: "blond", + skin_color: "fair", + eye_color: "blue", + birth_year: "19BBY", + gender: "male", + homeworld: "https://swapi.dev/api/planets/1/", + films: [ + "https://swapi.dev/api/films/1/", + "https://swapi.dev/api/films/2/", + "https://swapi.dev/api/films/3/", + "https://swapi.dev/api/films/6/" + ], + species: [], + vehicles: [ + "https://swapi.dev/api/vehicles/14/", + "https://swapi.dev/api/vehicles/30/" + ], + starships: [ + "https://swapi.dev/api/starships/12/", + "https://swapi.dev/api/starships/22/" + ], + created: new Date("2014-12-09T13:50:51.644000Z"), + edited: new Date("2014-12-20T21:17:56.891000Z"), + url: "https://swapi.dev/api/people/1/" + } + + it('Should return the result with specific fields only', () => { + const result = useGetRelatedProfiles(viewableCategories, currentProfile); + + const { vehicles, starships } = currentProfile; + + expect(JSON.stringify(result)).toBe(JSON.stringify({ + vehicles, + starships, + })) + }); + + it('Should not return the result with specific fields', () => { + const result = useGetRelatedProfiles(viewableCategories, currentProfile); + + const { vehicles, starships } = currentProfile; + + expect(JSON.stringify(result)).not.toBe(JSON.stringify({ + vehicles, + starships, + pilots: [] + })) + }); + + it('Should not return anything if profile object not passed', () => { + const result = useGetRelatedProfiles(viewableCategories, {} as MultiCategoryDetails); + + expect(JSON.stringify(result)).toBe(JSON.stringify({})) + }); + + it('Should exclude the category if not provided in the list', () => { + const result = useGetRelatedProfiles([SearchCategory.STARSHIPS], currentProfile); + + const { starships } = currentProfile; + + expect(JSON.stringify(result)).toBe(JSON.stringify({ + starships, + })) + }); +}) \ No newline at end of file diff --git a/src/hooks/profile/useProfile.ts b/src/hooks/profile/useProfile.ts index 2d7b85e..1fb5f34 100644 --- a/src/hooks/profile/useProfile.ts +++ b/src/hooks/profile/useProfile.ts @@ -1,6 +1,6 @@ import { useQuery } from '@tanstack/react-query'; import { SearchCategory } from "@api/endpoints/search" -import { getProfile } from "@api/endpoints/profile" +import { getProfiles } from "@api/endpoints/profile" export type UseProfileParams = { category: SearchCategory @@ -17,6 +17,13 @@ interface UseProfileResponse { remove?: () => void, } +/** + * useSearch is a hook that handles the api request to get the related search result if any + * @param {string=} category The categroy to search with + * @param {string} profileId The profile id this is related to + * @param {number[]} subIds The sub ids related to the profile + * @returns {UseSearchResponse} The result fo this request + */ export const useProfile = ({ category, profileId, subIds }: UseProfileParams): UseProfileResponse => { const { isLoading: isProfileLoading, @@ -24,7 +31,7 @@ export const useProfile = ({ category, profileId, subIds }: UseProfilePara error, isFetching, remove, - } = useQuery([`${category}-${profileId}`], () => getProfile({ category, ids: subIds }), { + } = useQuery([`${category}-${profileId}`], () => getProfiles({ category, ids: subIds }), { initialData: [], initialDataUpdatedAt: Date.now(), enabled: Boolean(category && profileId && subIds.length), diff --git a/src/hooks/profile/useProfileTableColumns.test.ts b/src/hooks/profile/useProfileTableColumns.test.ts new file mode 100644 index 0000000..23c0006 --- /dev/null +++ b/src/hooks/profile/useProfileTableColumns.test.ts @@ -0,0 +1,56 @@ +import { MultiCategoryDetails } from '@api/endpoints/profile'; +import { SearchCategory } from '@api/endpoints/search'; +import { useProfileTableColumns } from '@hooks/profile/useProfileTableColumns'; +import { toCapitalize } from '@utils/text'; + +describe('[Hook] useGetRelatedProfiles', () => { + const excludedColumns = [SearchCategory.PEOPLE, SearchCategory.VEHICLES, SearchCategory.SPECIES, SearchCategory.PLANETS, SearchCategory.STARSHIPS]; + const currentProfiles: MultiCategoryDetails[] = [{ + name: "Luke Skywalker", + height: 172, + mass: 77, + hair_color: "blond", + skin_color: "fair", + eye_color: "blue", + birth_year: "19BBY", + gender: "male", + homeworld: "https://swapi.dev/api/planets/1/", + films: [ + "https://swapi.dev/api/films/1/", + "https://swapi.dev/api/films/2/", + "https://swapi.dev/api/films/3/", + "https://swapi.dev/api/films/6/" + ], + species: [], + vehicles: [ + "https://swapi.dev/api/vehicles/14/", + "https://swapi.dev/api/vehicles/30/" + ], + starships: [ + "https://swapi.dev/api/starships/12/", + "https://swapi.dev/api/starships/22/" + ], + created: new Date("2014-12-09T13:50:51.644000Z"), + edited: new Date("2014-12-20T21:17:56.891000Z"), + url: "https://swapi.dev/api/people/1/" + }] + + it('Should return the result with specific fields only', () => { + const result = useProfileTableColumns(excludedColumns, currentProfiles); + + expect(JSON.stringify(result[0])).toBe(JSON.stringify({ + title: toCapitalize('name'), + dataIndex: 'name', + key: 'name-0', + width: 'auto', + ellipsis: true, + fixed: true, + })) + }); + + it('Should return empty array if no profiles given', () => { + const result = useProfileTableColumns(excludedColumns, []); + + expect(JSON.stringify(result)).toBe(JSON.stringify([])) + }); +}) \ No newline at end of file diff --git a/src/hooks/profile/useProfileTableColumns.ts b/src/hooks/profile/useProfileTableColumns.ts index 9c60c4d..83436b1 100644 --- a/src/hooks/profile/useProfileTableColumns.ts +++ b/src/hooks/profile/useProfileTableColumns.ts @@ -12,16 +12,17 @@ interface UserProfileTableColumnStruct { type UseProfileTableColumnsStruct = UserProfileTableColumnStruct[] -export const useProfileTableColumns = (categories: string[], data: MultiCategoryDetails[]): UseProfileTableColumnsStruct => { +export const useProfileTableColumns = (excludedCategories: string[], data: MultiCategoryDetails[]): UseProfileTableColumnsStruct => { const [columnDetails = {} as MultiCategoryDetails] = data; return Object.keys(columnDetails) .filter((key: string) => ![ - ...categories, + ...excludedCategories, 'homeworld', 'characters', 'url', ].includes(key)) + .filter((key) => key) .map((key, index) => ({ title: toCapitalize(key?.toString().replace(/([_])/gi, ' ')), dataIndex: key, diff --git a/src/hooks/profile/useProfileTableRows.test.ts b/src/hooks/profile/useProfileTableRows.test.ts new file mode 100644 index 0000000..ba19ce1 --- /dev/null +++ b/src/hooks/profile/useProfileTableRows.test.ts @@ -0,0 +1,60 @@ +import { MultiCategoryDetails } from '@api/endpoints/profile'; +import { SearchCategory } from '@api/endpoints/search'; +import { useProfileTableRows } from '@hooks/profile/useProfileTableRows'; + +describe('[Hook] useProfileTableRows', () => { + const excludedCategories = [SearchCategory.PEOPLE, SearchCategory.VEHICLES, SearchCategory.SPECIES, SearchCategory.PLANETS, SearchCategory.STARSHIPS]; + const currentProfiles: MultiCategoryDetails[] = [{ + name: "Luke Skywalker", + height: 172, + mass: 77, + hair_color: "blond", + skin_color: "fair", + eye_color: "blue", + birth_year: "19BBY", + gender: "male", + homeworld: "https://swapi.dev/api/planets/1/", + films: [ + "https://swapi.dev/api/films/1/", + "https://swapi.dev/api/films/2/", + "https://swapi.dev/api/films/3/", + "https://swapi.dev/api/films/6/" + ], + species: [], + vehicles: [ + "https://swapi.dev/api/vehicles/14/", + "https://swapi.dev/api/vehicles/30/" + ], + starships: [ + "https://swapi.dev/api/starships/12/", + "https://swapi.dev/api/starships/22/" + ], + created: new Date("2014-12-09T13:50:51.644000Z"), + edited: new Date("2014-12-20T21:17:56.891000Z"), + url: "https://swapi.dev/api/people/1/" + }] + + it('Should return the result with specific fields only', () => { + const result = useProfileTableRows(excludedCategories, currentProfiles); + + const [currentProfile = {} as MultiCategoryDetails] = currentProfiles; + const { homeworld, url, species, vehicles, starships, ...others } = currentProfile; + + expect(JSON.stringify(result)).toBe(JSON.stringify([{ + ...others, + key: 'Luke-Skywalker-0' + }])); + }) + + it('Should have always the key present', () => { + const result = useProfileTableRows(excludedCategories, currentProfiles); + + expect(result[0].key).toBe('Luke-Skywalker-0'); + }) + + it('Should return an empty array if no profile provided', () => { + const result = useProfileTableRows(excludedCategories, []); + + expect(JSON.stringify(result)).toBe(JSON.stringify([])); + }) +}) \ No newline at end of file diff --git a/src/hooks/profile/useProfileTableRows.ts b/src/hooks/profile/useProfileTableRows.ts index da79206..aa8882c 100644 --- a/src/hooks/profile/useProfileTableRows.ts +++ b/src/hooks/profile/useProfileTableRows.ts @@ -4,10 +4,10 @@ type UseProfileTableRowsStruct = (MultiCategoryDetails & { key: string })[] -export const useProfileTableRows = (viewableCategories: string[], data: MultiCategoryDetails[], max?: number): UseProfileTableRowsStruct => { +export const useProfileTableRows = (excludedCategories: string[], data: MultiCategoryDetails[], max?: number): UseProfileTableRowsStruct => { return data.map((currentProfile: MultiCategoryDetails) => Object.keys(currentProfile) .filter((key: string) => ![ - ...viewableCategories, + ...excludedCategories, 'homeworld', 'url', 'characters', diff --git a/src/hooks/search/useSearch.ts b/src/hooks/search/useSearch.ts index 57c3b94..0bd817e 100644 --- a/src/hooks/search/useSearch.ts +++ b/src/hooks/search/useSearch.ts @@ -16,6 +16,14 @@ interface UseSearchResponse { remove?: () => void, } +/** + * useSearch is a hook that handles the api request to get the related search result if any + * @param {Object} search A new instance of searching request + * @param {string=} category The categroy to search with + * @param {string} searchValue The value to be searched + * @param {boolean=} canRefetch If this value should be forcefully refetched & clear cache + * @returns {UseSearchResponse} The result fo this request + */ export const useSearch = ({ category, searchValue, canRefetch }: UseSearchParams): UseSearchResponse => { const { isLoading: isSearchLoading, diff --git a/src/index.css b/src/index.css index ec2585e..88606d8 100644 --- a/src/index.css +++ b/src/index.css @@ -1,13 +1,12 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} +@import '~antd/dist/antd.css'; -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; +#components-layout-demo-fixed .logo { + float: left; + width: 120px; + height: 31px; + margin: 16px 24px 16px 0; + background: rgba(255, 255, 255, 0.2); } +.site-layout .site-layout-background { + background: #fff; +} \ No newline at end of file diff --git a/src/index.tsx b/src/index.tsx index 771de46..3ee5afb 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -8,7 +8,7 @@ import App from './App'; import reportWebVitals from './reportWebVitals'; import { QueryClientProvider } from '@tanstack/react-query'; import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; -import queryClient from './services/QueryClient'; +import queryClient from '@plugins/QueryClient'; import { RecoilRoot, } from 'recoil'; diff --git a/src/pages/errors/404.tsx b/src/pages/errors/404.tsx index 4c22e13..2c30203 100644 --- a/src/pages/errors/404.tsx +++ b/src/pages/errors/404.tsx @@ -1,7 +1,7 @@ import { useNavigate } from "react-router-dom"; import { Button, Result } from 'antd'; -function NoMatch() { +const NoMatch = () => { const navigation = useNavigate(); return ( diff --git a/src/pages/errors/general.tsx b/src/pages/errors/general.tsx index e0b3977..2466e1a 100644 --- a/src/pages/errors/general.tsx +++ b/src/pages/errors/general.tsx @@ -1,6 +1,6 @@ import { Button, Result } from 'antd'; -function GeneralError({ onRetry = () => {} }) { +const GeneralError = ({ onRetry = () => {} }) => { return ( currentCategory !== SearchCategory.ALL); +const excludedCategories = Object.values(SearchCategory).filter((currentCategory) => currentCategory !== SearchCategory.ALL); -function Profile() { +const Profile = () => { let { id } = useParams<"id">(); let { category = '' } = useParams<"category">(); const navigation = useNavigate(); @@ -34,7 +35,7 @@ function Profile() { const [currentProfile = {} as MultiCategoryDetails,] = data; const relatedProfiles = useGetRelatedProfiles(viewableCategories, currentProfile) - const displayData = useDisplayableDetails(viewableCategories, currentProfile) + const displayData = useDisplayableDetails(excludedCategories, currentProfile) const onErrorRetry = useCallback(() => { navigation(`/${category}/${id}`, { @@ -57,7 +58,7 @@ function Profile() { return ( } > diff --git a/src/pages/search/index.tsx b/src/pages/search/index.tsx index 979748b..d5b7841 100644 --- a/src/pages/search/index.tsx +++ b/src/pages/search/index.tsx @@ -14,7 +14,7 @@ import useSearchCanRefetch from '@hooks/search/atoms/useSearchCanRefetch'; const { Search } = Input; -function MainSearch() { +const MainSearch = () => { const { searchValue, setSearchValue } = useSearchValue(); const { setSearchCanRefetch } = useSearchCanRefetch(); const { searchCategory, setSearchCategory } = useSearchCategory(); diff --git a/src/services/QueryClient.ts b/src/plugins/QueryClient.ts similarity index 81% rename from src/services/QueryClient.ts rename to src/plugins/QueryClient.ts index a11674a..f4b000e 100644 --- a/src/services/QueryClient.ts +++ b/src/plugins/QueryClient.ts @@ -2,6 +2,10 @@ import { QueryClient } from '@tanstack/react-query'; import { isApiError }from '@utils/api' +/** + * @documentation https://tanstack.com/query/v4/?from=reactQueryV3&original=https://react-query-v3.tanstack.com/ + */ + const queryClient = new QueryClient({ defaultOptions: { queries: { diff --git a/src/plugins/routing.tsx b/src/plugins/routing.tsx index 69bad72..a987510 100644 --- a/src/plugins/routing.tsx +++ b/src/plugins/routing.tsx @@ -4,6 +4,9 @@ import MainSearch from '@pages/search' import Profile from '@pages/profile' import SearchList from '@components/search/SearchList' +/** + * @documentation https://reactrouter.com/en/main + */ const routes: RouteObject[] = [ { path: "/", diff --git a/src/services/ApiService.ts b/src/services/ApiService.ts index 990994b..f6f05a1 100644 --- a/src/services/ApiService.ts +++ b/src/services/ApiService.ts @@ -1,5 +1,8 @@ import axios, { AxiosError, AxiosResponse, AxiosRequestConfig } from 'axios' +/** + * @documentation https://axios-http.com/docs/intro + */ const api = axios.create({ baseURL: 'https://swapi.dev/api', }) diff --git a/src/utils/api.ts b/src/utils/api.ts index 787a23f..4bb79a6 100644 --- a/src/utils/api.ts +++ b/src/utils/api.ts @@ -1,4 +1,9 @@ import type { AxiosError } from "axios"; +/** + * Check if current error is related to API + * @param {object} error Potentially unknown object error + * @returns {boolean} If this is an error of Api + */ export const isApiError = (error: unknown): error is AxiosError => (error as AxiosError).isAxiosError !== undefined; \ No newline at end of file diff --git a/src/utils/readable.test.ts b/src/utils/readable.test.ts new file mode 100644 index 0000000..6af0427 --- /dev/null +++ b/src/utils/readable.test.ts @@ -0,0 +1,22 @@ +import { SearchCategory } from '@api/endpoints/search'; +import { categoryToSingularHumanReadable } from '@utils/readable'; + +describe('[Util] Readable', () => { + it('Should be "Unknown" on category ALL', () => { + const result = categoryToSingularHumanReadable(SearchCategory.ALL); + + expect(result).toBe('Unknown'); + }) + + it('Should be "Planet" on category PLANETS', () => { + const result = categoryToSingularHumanReadable(SearchCategory.PLANETS); + + expect(result).toBe('Planet'); + }) + + it('Should be "Vehicle" on category VEHICLES', () => { + const result = categoryToSingularHumanReadable(SearchCategory.VEHICLES); + + expect(result).toBe('Vehicle'); + }) +}); \ No newline at end of file diff --git a/src/utils/readable.ts b/src/utils/readable.ts index aad8a81..96e2050 100644 --- a/src/utils/readable.ts +++ b/src/utils/readable.ts @@ -1,6 +1,11 @@ import { SearchCategory } from "@api/endpoints/search" -export const categoryToReadable = (category: string) => { +/** + * Get the category translated | This is not best way of doing it + * @param {string} category The category to be translated + * @returns {string} The category phrase translated + */ +export const categoryToSingularHumanReadable = (category: string) => { switch (category) { case SearchCategory.PEOPLE: return 'Person' @@ -10,6 +15,12 @@ export const categoryToReadable = (category: string) => { return 'Starship' case SearchCategory.VEHICLES: return 'Vehicle' + case SearchCategory.SPECIES: + return 'Species' + case SearchCategory.PILOTS: + return 'Pilot' + case SearchCategory.PLANETS: + return 'Planet' default: return 'Unknown' } diff --git a/src/utils/text.test.ts b/src/utils/text.test.ts new file mode 100644 index 0000000..4444a8f --- /dev/null +++ b/src/utils/text.test.ts @@ -0,0 +1,35 @@ +import { toCapitalize } from '@utils/text'; + +describe('[Util] Text', () => { + it('Should one word be capitalized', () => { + const str = 'test'; + + const result = toCapitalize(str); + + expect(result).toBe('Test'); + }) + + it('Should multiple word be capitalized', () => { + const str = 'test string to be capitalized'; + + const result = toCapitalize(str); + + expect(result).toBe('Test String To Be Capitalized'); + }) + + it('Should not be fully uppercase', () => { + const str = 'test string to be capitalized'; + + const result = toCapitalize(str); + + expect(result).not.toBe(str.toUpperCase()); + }) + + it('Should not be fully lowercase', () => { + const str = 'test string to be capitalized'; + + const result = toCapitalize(str); + + expect(result).not.toBe(str.toLowerCase()); + }) +}); \ No newline at end of file diff --git a/src/utils/text.ts b/src/utils/text.ts index de97b66..325d03e 100644 --- a/src/utils/text.ts +++ b/src/utils/text.ts @@ -1,2 +1,8 @@ + +/** + * Transform non captilized to captilized string + * @param {string} text The text to be transformed into capitlized + * @returns {string} The captilized string + */ export const toCapitalize = (text: string) => - text.split(' ').map((word) =>`${word.charAt(0).toUpperCase()}${word.slice(1)}`).join(' ') \ No newline at end of file + text.split(' ').map((word) =>`${word.charAt(0).toUpperCase()}${word.toLowerCase().slice(1)}`).join(' ') \ No newline at end of file