From 0ef4d19734694b441aa193ab26a3218d5a71b1ae Mon Sep 17 00:00:00 2001 From: Steve Rydz Date: Tue, 4 Jul 2023 11:08:27 +0100 Subject: [PATCH] Add models table (#4316) --- package.json | 1 + static/js/brand-store/components/App/App.tsx | 72 +++++++----- .../components/Models/Models.test.tsx | 45 ++++++++ .../brand-store/components/Models/Models.tsx | 104 +++++++++++++++-- .../components/Models/models-data.js | 106 ++++++++++++++++++ static/js/brand-store/types/shared.ts | 9 ++ .../utils/getFilteredModels.test.ts | 46 ++++++++ .../js/brand-store/utils/getFilteredModels.ts | 22 ++++ static/js/brand-store/utils/index.ts | 4 + .../js/brand-store/utils/maskString.test.ts | 21 ++++ static/js/brand-store/utils/maskString.ts | 20 ++++ yarn.lock | 85 +++++++++++++- 12 files changed, 497 insertions(+), 38 deletions(-) create mode 100644 static/js/brand-store/components/Models/Models.test.tsx create mode 100644 static/js/brand-store/components/Models/models-data.js create mode 100644 static/js/brand-store/utils/getFilteredModels.test.ts create mode 100644 static/js/brand-store/utils/getFilteredModels.ts create mode 100644 static/js/brand-store/utils/index.ts create mode 100644 static/js/brand-store/utils/maskString.test.ts create mode 100644 static/js/brand-store/utils/maskString.ts diff --git a/package.json b/package.json index 5d72438944..fa1bc29c12 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,7 @@ "react-dnd-html5-backend": "16.0.1", "react-dom": "18.2.0", "react-hook-form": "7.43.2", + "react-query": "3.39.3", "react-redux": "8.0.5", "react-router-dom": "6.8.2", "react-sortable-hoc": "2.0.0", diff --git a/static/js/brand-store/components/App/App.tsx b/static/js/brand-store/components/App/App.tsx index 2af0366e5a..78642333ce 100644 --- a/static/js/brand-store/components/App/App.tsx +++ b/static/js/brand-store/components/App/App.tsx @@ -1,5 +1,6 @@ import React, { useEffect } from "react"; import { useSelector, useDispatch } from "react-redux"; +import { QueryClient, QueryClientProvider } from "react-query"; import { BrowserRouter as Router, Routes, @@ -29,42 +30,53 @@ function App() { const brandStoresList: StoresList = useSelector(brandStoresListSelector); const dispatch = useDispatch(); + const queryClient = new QueryClient({ + defaultOptions: { + queries: { + refetchOnWindowFocus: false, + refetchOnReconnect: false, + }, + }, + }); + useEffect(() => { dispatch(fetchStores() as any); }, []); return ( -
- - - - ) : brandStoresList[0].id === "ubuntu" ? ( - // Don't redirect to the global store by default - - ) : ( - - ) - ) : null - } - /> - } /> - } /> - } /> - } /> - } /> - } - /> - } /> - -
+ +
+ + + + ) : brandStoresList[0].id === "ubuntu" ? ( + // Don't redirect to the global store by default + + ) : ( + + ) + ) : null + } + /> + } /> + } /> + } /> + } /> + } /> + } + /> + } /> + +
+
); } diff --git a/static/js/brand-store/components/Models/Models.test.tsx b/static/js/brand-store/components/Models/Models.test.tsx new file mode 100644 index 0000000000..7909ee486d --- /dev/null +++ b/static/js/brand-store/components/Models/Models.test.tsx @@ -0,0 +1,45 @@ +import React from "react"; +import { BrowserRouter } from "react-router-dom"; +import { render, screen } from "@testing-library/react"; + +import "@testing-library/jest-dom"; + +import Models from "./Models"; + +let mockFilterQuery = "model-1"; + +jest.mock("react-router-dom", () => { + return { + ...jest.requireActual("react-router-dom"), + useSearchParams: () => [new URLSearchParams({ filter: mockFilterQuery })], + }; +}); + +describe("Models", () => { + it("displays a filter input", () => { + render( + + + + ); + expect(screen.getByLabelText("Search models")).toBeInTheDocument(); + }); + + it("populates filter with the filter query parameter", () => { + render( + + + + ); + expect(screen.getByLabelText("Search models")).toHaveValue(mockFilterQuery); + }); + + it("displays a table of models", () => { + render( + + + + ); + expect(screen.getByTestId("models-table")).toBeInTheDocument(); + }); +}); diff --git a/static/js/brand-store/components/Models/Models.tsx b/static/js/brand-store/components/Models/Models.tsx index 4a424f4536..cc0e8494a7 100644 --- a/static/js/brand-store/components/Models/Models.tsx +++ b/static/js/brand-store/components/Models/Models.tsx @@ -1,10 +1,21 @@ import React from "react"; -import { Link, useParams } from "react-router-dom"; +import { Link, useParams, useSearchParams } from "react-router-dom"; +import { format } from "date-fns"; +import { MainTable, SearchBox, Row, Col } from "@canonical/react-components"; import SectionNav from "../SectionNav"; +import { getFilteredModels, maskString } from "../../utils"; + +import type { Model } from "../../types/shared"; + +// This is temporary until the API is connected +import modelsData from "./models-data"; + function Models() { const { id } = useParams(); + const [searchParams, setSearchParams] = useSearchParams(); + const models = getFilteredModels(modelsData.data, searchParams.get("filter")); return (
@@ -13,13 +24,92 @@ function Models() {
+ + + {/* Placeholder for "Create new model" button */} + + + { + if (value) { + setSearchParams({ + filter: value, + }); + } else { + setSearchParams(); + } + }} + /> + +
-

This is where the models table will be

-

- - Example model page - -

+ {models.length > 0 && ( + { + return { + columns: [ + { + content: ( + + {model.name} + + ), + }, + { + content: maskString(model["api-key"]), + className: "u-align--right", + }, + { + content: format( + new Date(model["modified-at"]), + "dd/MM/yyyy" + ), + className: "u-align--right", + }, + { + content: format( + new Date(model["created-at"]), + "dd/MM/yyyy" + ), + className: "u-align--right", + }, + ], + sortData: { + name: model.name, + "modified-at": model["modified-at"], + "created-at": model["created-at"], + }, + }; + })} + /> + )}
diff --git a/static/js/brand-store/components/Models/models-data.js b/static/js/brand-store/components/Models/models-data.js new file mode 100644 index 0000000000..43509454b1 --- /dev/null +++ b/static/js/brand-store/components/Models/models-data.js @@ -0,0 +1,106 @@ +const modelsData = { + success: true, + message: "The request has been successful", + data: [ + { + name: "model-1", + "api-key": "e15a9abc390b4514a35752f5851e27b8", + "created-at": "2022-03-29T13:03:11.095Z", + "created-by": "publisherId", + "modified-at": "2023-06-27T13:06:25.541Z", + "modified-by": "publisherId", + }, + { + name: "model-2", + "api-key": "80eb997804364d1a9008777584082e3d", + "created-at": "2018-07-14T13:03:35.452Z", + "created-by": "publisherId", + "modified-at": "2023-06-29T13:06:52.630Z", + "modified-by": "publisherId", + }, + { + name: "model-3", + "api-key": "fea502ee59c249369073b96034b56770", + "created-at": "2021-10-31T13:07:10.090Z", + "created-by": "publisherId", + "modified-at": "2023-06-29T13:03:35.452Z", + "modified-by": "publisherId", + }, + { + name: "model-4", + "api-key": "a19e3ac3d7d442e39c0d", + "created-at": "2022-03-29T13:03:11.095Z", + "created-by": "publisherId", + "modified-at": "2023-06-27T13:06:25.541Z", + "modified-by": "publisherId", + }, + { + name: "model-5", + "api-key": "d24277fd31a8450ca326", + "created-at": "2018-07-14T13:03:35.452Z", + "created-by": "publisherId", + "modified-at": "2023-06-29T13:06:52.630Z", + "modified-by": "publisherId", + }, + { + name: "model-6", + "api-key": "e9797541fbe44cf6b788", + "created-at": "2021-10-31T13:07:10.090Z", + "created-by": "publisherId", + "modified-at": "2023-06-29T13:03:35.452Z", + "modified-by": "publisherId", + }, + { + name: "model-7", + "api-key": "9d022dcdb4b4413bb1a0", + "created-at": "2022-03-29T13:03:11.095Z", + "created-by": "publisherId", + "modified-at": "2023-06-27T13:06:25.541Z", + "modified-by": "publisherId", + }, + { + name: "model-8", + + "api-key": "892f97b614bf4c70a6ac", + "created-at": "2018-07-14T13:03:35.452Z", + "created-by": "publisherId", + "modified-at": "2023-06-29T13:06:52.630Z", + "modified-by": "publisherId", + }, + { + name: "model-9", + "api-key": "48135fc256a840638dba", + + "created-at": "2021-10-31T13:07:10.090Z", + "created-by": "publisherId", + "modified-at": "2023-06-29T13:03:35.452Z", + "modified-by": "publisherId", + }, + { + name: "model-10", + "api-key": "87a5cf9c6bc84f219c34", + "created-at": "2022-03-29T13:03:11.095Z", + "created-by": "publisherId", + "modified-at": "2023-06-27T13:06:25.541Z", + "modified-by": "publisherId", + }, + { + name: "model-11", + "api-key": "1f7a61567e944e53a584", + "created-at": "2018-07-14T13:03:35.452Z", + "created-by": "publisherId", + "modified-at": "2023-06-29T13:06:52.630Z", + "modified-by": "publisherId", + }, + { + name: "model-12", + "api-key": "437d5599c88a4d15840d", + "created-at": "2021-10-31T13:07:10.090Z", + "created-by": "publisherId", + "modified-at": "2023-06-29T13:03:35.452Z", + "modified-by": "publisherId", + }, + ], +}; + +export default modelsData; diff --git a/static/js/brand-store/types/shared.ts b/static/js/brand-store/types/shared.ts index 26fb4b539f..8f56dcd362 100644 --- a/static/js/brand-store/types/shared.ts +++ b/static/js/brand-store/types/shared.ts @@ -94,3 +94,12 @@ export type Store = { snaps: SnapsList; userHasAccess: boolean; }; + +export type Model = { + name: string; + "api-key": string; + "created-at": string; + "created-by": string; + "modified-at": string; + "modified-by": string; +}; diff --git a/static/js/brand-store/utils/getFilteredModels.test.ts b/static/js/brand-store/utils/getFilteredModels.test.ts new file mode 100644 index 0000000000..acdeac63b6 --- /dev/null +++ b/static/js/brand-store/utils/getFilteredModels.test.ts @@ -0,0 +1,46 @@ +import getFilteredModels from "./getFilteredModels"; + +const mockModels = [ + { + name: "model-1", + "api-key": "e15a9abc390b4514a35752f5851e27b8", + "created-at": "2022-03-29T13:03:11.095Z", + "created-by": "publisherId", + "modified-at": "2023-06-27T13:06:25.541Z", + "modified-by": "publisherId", + }, + { + name: "model-2", + "api-key": "80eb997804364d1a9008777584082e3d", + "created-at": "2018-07-14T13:03:35.452Z", + "created-by": "publisherId", + "modified-at": "2023-06-29T13:06:52.630Z", + "modified-by": "publisherId", + }, + { + name: "model-3", + "api-key": "fea502ee59c249369073b96034b56770", + "created-at": "2021-10-31T13:07:10.090Z", + "created-by": "publisherId", + "modified-at": "2023-06-29T13:03:35.452Z", + "modified-by": "publisherId", + }, +]; + +describe("getFilteredModels", () => { + it("returns unfiltered models if no filter query", () => { + expect(getFilteredModels(mockModels).length).toEqual(mockModels.length); + expect(getFilteredModels(mockModels)[0].name).toEqual(mockModels[0].name); + expect(getFilteredModels(mockModels)[1].name).toEqual(mockModels[1].name); + expect(getFilteredModels(mockModels)[2].name).toEqual(mockModels[2].name); + }); + + it("returns no models if filter query doesn't match", () => { + expect(getFilteredModels(mockModels, "foobar").length).toEqual(0); + }); + + it("returns filtered models if query matches", () => { + expect(getFilteredModels(mockModels, "model-2").length).toBe(1); + expect(getFilteredModels(mockModels, "model-2")[0].name).toEqual("model-2"); + }); +}); diff --git a/static/js/brand-store/utils/getFilteredModels.ts b/static/js/brand-store/utils/getFilteredModels.ts new file mode 100644 index 0000000000..4bd1d2f550 --- /dev/null +++ b/static/js/brand-store/utils/getFilteredModels.ts @@ -0,0 +1,22 @@ +import type { Model } from "../types/shared"; + +function getFilteredModels(models: Array, filterQuery?: string | null) { + if (!filterQuery) { + return models; + } + + return models.filter((model: Model) => { + if ( + model.name.includes(filterQuery) || + model["api-key"].includes(filterQuery) || + model["created-at"].includes(filterQuery) || + model["modified-at"].includes(filterQuery) + ) { + return true; + } + + return false; + }); +} + +export default getFilteredModels; diff --git a/static/js/brand-store/utils/index.ts b/static/js/brand-store/utils/index.ts new file mode 100644 index 0000000000..24e0228cb9 --- /dev/null +++ b/static/js/brand-store/utils/index.ts @@ -0,0 +1,4 @@ +import getFilteredModels from "./getFilteredModels"; +import maskString from "./maskString"; + +export { getFilteredModels, maskString }; diff --git a/static/js/brand-store/utils/maskString.test.ts b/static/js/brand-store/utils/maskString.test.ts new file mode 100644 index 0000000000..2d7473f0da --- /dev/null +++ b/static/js/brand-store/utils/maskString.test.ts @@ -0,0 +1,21 @@ +import maskString from "./maskString"; + +describe("maskString", () => { + const str = "761bbec69e2844958fcd"; + + it("returns the given argument if less than or equal to 4 characters", () => { + expect(maskString("a")).toEqual("a"); + expect(maskString("ab")).toEqual("ab"); + expect(maskString("abc")).toEqual("abc"); + expect(maskString("abcd")).toEqual("abcd"); + expect(maskString("abcde")).toEqual("*bcde"); + }); + + it("returns a string of asterisks and 4 characters", () => { + expect(maskString(str)).toEqual("****************8fcd"); + }); + + it("returns a string that same length as its given argument", () => { + expect(maskString(str).length).toEqual(str.length); + }); +}); diff --git a/static/js/brand-store/utils/maskString.ts b/static/js/brand-store/utils/maskString.ts new file mode 100644 index 0000000000..883d1c1fc8 --- /dev/null +++ b/static/js/brand-store/utils/maskString.ts @@ -0,0 +1,20 @@ +function maskString(str: string) { + const visibleCharacterCount = 4; + + if (str.length < visibleCharacterCount) { + return str; + } + + const strLength = str.length; + const strEnd = str.slice(strLength - visibleCharacterCount, strLength); + + let strMask = ""; + + for (let i = 0, ii = strLength - visibleCharacterCount; i < ii; i++) { + strMask += "*"; + } + + return `${strMask}${strEnd}`; +} + +export default maskString; diff --git a/yarn.lock b/yarn.lock index 071a709e62..d02ca5bee2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -993,6 +993,13 @@ dependencies: regenerator-runtime "^0.13.11" +"@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.5.tgz#8564dd588182ce0047d55d7a75e93921107b57ec" + integrity sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA== + dependencies: + regenerator-runtime "^0.13.11" + "@babel/template@^7.18.10", "@babel/template@^7.20.7", "@babel/template@^7.3.3": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8" @@ -2539,6 +2546,11 @@ balanced-match@^2.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-2.0.0.tgz#dc70f920d78db8b858535795867bf48f820633d9" integrity sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA== +big-integer@^1.6.16: + version "1.6.51" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" + integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg== + binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" @@ -2559,6 +2571,20 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" +broadcast-channel@^3.4.1: + version "3.7.0" + resolved "https://registry.yarnpkg.com/broadcast-channel/-/broadcast-channel-3.7.0.tgz#2dfa5c7b4289547ac3f6705f9c00af8723889937" + integrity sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg== + dependencies: + "@babel/runtime" "^7.7.2" + detect-node "^2.1.0" + js-sha3 "0.8.0" + microseconds "0.2.0" + nano-time "1.0.0" + oblivious-set "1.0.0" + rimraf "3.0.2" + unload "2.2.0" + browserslist@^4.14.5, browserslist@^4.21.3, browserslist@^4.21.4, browserslist@^4.21.5: version "4.21.5" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7" @@ -3296,6 +3322,11 @@ detect-newline@^3.0.0: resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== +detect-node@^2.0.4, detect-node@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" + integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== + diff-sequences@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" @@ -5104,6 +5135,11 @@ js-sdsl@^4.1.4: resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.3.0.tgz#aeefe32a451f7af88425b11fdb5f58c90ae1d711" integrity sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ== +js-sha3@0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -5396,6 +5432,14 @@ markdown-it@13.0.1: mdurl "^1.0.1" uc.micro "^1.0.5" +match-sorter@^6.0.2: + version "6.3.1" + resolved "https://registry.yarnpkg.com/match-sorter/-/match-sorter-6.3.1.tgz#98cc37fda756093424ddf3cbc62bfe9c75b92bda" + integrity sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw== + dependencies: + "@babel/runtime" "^7.12.5" + remove-accents "0.4.2" + mathml-tag-names@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" @@ -5447,6 +5491,11 @@ micromatch@^4.0.0, micromatch@^4.0.4, micromatch@^4.0.5: braces "^3.0.2" picomatch "^2.3.1" +microseconds@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/microseconds/-/microseconds-0.2.0.tgz#233b25f50c62a65d861f978a4a4f8ec18797dc39" + integrity sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA== + mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" @@ -5503,6 +5552,13 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +nano-time@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/nano-time/-/nano-time-1.0.0.tgz#b0554f69ad89e22d0907f7a12b0993a5d96137ef" + integrity sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA== + dependencies: + big-integer "^1.6.16" + nanoid@3.3.4, nanoid@^3.3.4: version "3.3.4" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" @@ -5643,6 +5699,11 @@ object.values@^1.1.6: define-properties "^1.1.4" es-abstract "^1.20.4" +oblivious-set@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/oblivious-set/-/oblivious-set-1.0.0.tgz#c8316f2c2fb6ff7b11b6158db3234c49f733c566" + integrity sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw== + once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -6116,6 +6177,15 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== +react-query@3.39.3: + version "3.39.3" + resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.39.3.tgz#4cea7127c6c26bdea2de5fb63e51044330b03f35" + integrity sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g== + dependencies: + "@babel/runtime" "^7.5.5" + broadcast-channel "^3.4.1" + match-sorter "^6.0.2" + react-redux@8.0.5: version "8.0.5" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-8.0.5.tgz#e5fb8331993a019b8aaf2e167a93d10af469c7bd" @@ -6302,6 +6372,11 @@ regjsparser@^0.9.1: dependencies: jsesc "~0.5.0" +remove-accents@0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/remove-accents/-/remove-accents-0.4.2.tgz#0a43d3aaae1e80db919e07ae254b285d9e1c7bb5" + integrity sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA== + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -6367,7 +6442,7 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@^3.0.2: +rimraf@3.0.2, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== @@ -7169,6 +7244,14 @@ universalify@^2.0.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== +unload@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/unload/-/unload-2.2.0.tgz#ccc88fdcad345faa06a92039ec0f80b488880ef7" + integrity sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA== + dependencies: + "@babel/runtime" "^7.6.2" + detect-node "^2.0.4" + update-browserslist-db@^1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3"